Это более важный комментарий, и поэтому неявно развернутые необязательные опции могут быть обманчивы, когда дело доходит до отладки nil
значений.
Подумайте о следующем коде: он компилируется без ошибок / предупреждений:
c1.address.city = c3.address.city
И все же во время выполнения выдает следующую ошибку: Неустранимая ошибка: неожиданно обнаружен ноль при развертывании необязательного значения
Можете ли вы сказать мне, какой объект nil
?
Вы не можете!
Полный код будет:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var c1 = NormalContact()
let c3 = BadContact()
c1.address.city = c3.address.city // compiler hides the truth from you and then you sudden get a crash
}
}
struct NormalContact {
var address : Address = Address(city: "defaultCity")
}
struct BadContact {
var address : Address!
}
struct Address {
var city : String
}
Короче говоря, используя var address : Address!
, вы скрываете возможность того, что переменная может быть nil
от других читателей. И когда он падает, вы говорите: «Что, черт возьми ?! Мой address
не является дополнительным, так почему я терплю крах?!.
Следовательно, лучше написать так:
c1.address.city = c2.address!.city // ERROR: Fatal error: Unexpectedly found nil while unwrapping an Optional value
Можете ли вы сказать мне, что это был за nil
?
На этот раз код стал более понятным для вас. Вы можете рационализировать и подумать, что вероятно, это был параметр address
, который был принудительно развернут.
Полный код был бы:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var c1 = NormalContact()
let c2 = GoodContact()
c1.address.city = c2.address!.city
c1.address.city = c2.address?.city // not compile-able. No deceiving by the compiler
c1.address.city = c2.address.city // not compile-able. No deceiving by the compiler
if let city = c2.address?.city { // safest approach. But that's not what I'm talking about here.
c1.address.city = city
}
}
}
struct NormalContact {
var address : Address = Address(city: "defaultCity")
}
struct GoodContact {
var address : Address?
}
struct Address {
var city : String
}
Вы можете использовать что-то вроде cglib для генерации кода на лету
In java6 has been added the possibility to transform any already loaded class. Take a look at the changes in the java.lang.instrument package
Для интерфейсов существует java.lang.reflect.Proxy
.
Для классов вам понадобится сторонняя библиотека или напишите небольшой фрагмент кода. . Обычно динамическое создание классов таким образом заключается в создании имитаций для тестирования.
Существует также инструментальный API, который позволяет изменять классы. Вы также можете изменять классы с помощью специального загрузчика классов или просто файлов классов на диске.
Я написал статью для java.net о том, как прозрачно добавлять операторы протоколирования к классу, когда он загружается загрузчиком классов с помощью агента java.
Это использует библиотеку Javassist для управления байтовым кодом, включая использование компилятора Javassist для генерации дополнительного байт-кода, который затем вставляется в соответствующее место, а затем полученный класс предоставляется загрузчику классов.
Уточненная версия доступна с slf4j
проект.
Если я правильно понял, основная проблема, которая вас беспокоит, заключается в том, как передать делегат статического метода (как в C #) через метод интерфейса экземпляра.
Вы можете проверить эту статью : Программист на Java изучает делегатов C # , где показано, как получить ссылку на ваш статический метод и вызвать его. Затем вы можете создать класс-оболочку, который принимает имя статического метода в своем конструкторе и реализует ваш базовый класс для вызова статического метода из метода экземпляра.