1) Конструктор
class MyClass(private val myInterface: MyInterface) { ... }
Таким образом, myInterface
является неизменным. Вы можете быть уверены, что это никогда не будет нулевым.
2) После создания объекта - null
class MyClass(var myInterface: MyInterface? = null) { ... }
Теперь myInterface
является изменяемым и может быть нулевым в любое время. Вы можете безопасно получить к нему доступ через myInterface?.someMethod()
(если myInterface
- нулевой вызов не будет вызван). Для доступа и назначения слушателя используйте myClassInstance.myInterface = myInterfaceInstance
.
Из-за параметра по умолчанию вы можете создать свой класс с параметром конструктора или без него:
val myClass1 = MyClass()
val myClass2 = MyClass(interfaceInstanceOrNull)
3) После создания объекта - lateinit
class MyClass(myInterface: MyInterface? = null) {
lateinit var _myInterface: MyInterface
init {
if (myInterface != null) { _myInterface = myInterface }
}
}
На мой взгляд, худшее решение. lateinit
предназначен для введения поля после создания, для DI-фреймворков, таких как dagger. Если вы попытаетесь вызвать метод на myInterface
, если он еще не инициализирован, UninitializedPropertyAccessException
будет брошено. Вы можете проверить, инициализировано ли свойство так:
if (::_myProperty.isInitialized) { _myProperty.doSth() }
По-моему, вы должны использовать первый или второй подход. Как я понимаю, вы не всегда можете инициировать объект с экземпляром MyInterface, поэтому второй вариант кажется правильным для ваших целей.