Котлин считает свойство неинициализированным до конца его инициализатора, поэтому он не может использоваться внутри собственного инициализатора даже в лямбдах. Эта семантика аналогична ограничению использования локальной переменной внутри ее инициализатора .
Существует несколько способов:
this
объявленного объекта: private var runnable: Runnable = object : Runnable {
override fun run() {
/* Do something very important */
handler.postDelayed(this, 5000)
}
}
Это хорошо работает lateinit var
или делегированное свойство с Delegates.notNull()
. ] : private lateinit var runnable: Runnable
init {
runnable = Runnable {
/* Do something very important */
handler.postDelayed(runnable, 5000)
}
}
Тот же инициализатор будет работать с этим объявлением: private var runnable: Runnable by Delegates.notNull()
class SelfReference(val initializer: SelfReference.() -> T) {
val self: T by lazy {
inner ?: throw IllegalStateException("Do not use `self` until initialized.")
}
private val inner = initializer()
}
fun selfReference(initializer: SelfReference.() -> T): T {
return SelfReference(initializer).self
}
И тогда вы можете написать что-то вроде private var runnable: Runnable = selfReference {
Runnable {
/* Do something very important */
handler.postDelayed(self, 5000)
}
}
Они совместно используют ту же подпись, но они - все еще различные типы.
Роберт С. совершенно прав; например: -
class A {
static void Main() {
Func<int, bool> func = i => i > 100;
Predicate<int> pred = i => i > 100;
Test<int>(pred, 150);
Test<int>(func, 150); // Error
}
static void Test<T>(Predicate<T> pred, T val) {
Console.WriteLine(pred(val) ? "true" : "false");
}
}
Даже без обобщений вы можете иметь разные типы делегатов, которые идентичны в сигнатурах и типах возвращаемых данных. Например:
namespace N
{
// Represents a method that takes in a string and checks to see
// if this string has some predicate (i.e. meets some criteria)
// or not.
internal delegate bool StringPredicate(string stringToTest);
// Represents a method that takes in a string representing a
// yes/no or true/false value and returns the boolean value which
// corresponds to this string
internal delegate bool BooleanParser(string stringToConvert);
}
В приведенном выше примере два неуниверсальных типа имеют одинаковую сигнатуру и возвращаемый тип. (И на самом деле также, как Predicate<string>
и Func<string, bool>
). Но, как я пытался указать, «значение» двух разных.
Это похоже на то, что если я сделаю два класса, class Car { string Color; decimal Price; }
и class Person { string FullName; decimal BodyMassIndex; }
, то просто потому, что оба они содержат string
и decimal
, это не значит, что они «одинаковые» тип.
Более гибкое семейство Func
появилось только в .NET 3.5, поэтому оно будет функционально дублировать типы, которые должны были быть включены ранее по необходимости.
(Плюс name Предикат
сообщает предполагаемое использование читателям исходного кода)