lazy и lateinit
Часть раздела Объектно-ориентированное программирование путешествия по Kotlin на Coddy. Урок 10 из 57.
by lazy { ... } откладывает вычисление val до момента его первого чтения, а затем запоминает результат. Это подходит для значений, вычисление которых требует больших затрат или которые нужны не всегда:
class Report(val rows: List<Int>) {
val summary: String by lazy {
println("computing summary")
"total ${rows.sum()}"
}
}Внутри main:
val r = Report(listOf(3, 4))
println("created")
println(r.summary)
println(r.summary)Вывод:
created
computing summary
total 7
total 7Блок выполняется один раз: при втором чтении выше использовался сохранённый результат. В отличие от пользовательского геттера, который выполняется при каждом чтении, lazy вычисляет значение один раз и кэширует его:
class Demo {
var reads = 0
val viaGetter: Int
get() { reads++; return 42 }
val viaLazy: Int by lazy { reads++; 42 }
}Внутри main:
val d = Demo()
repeat(3) { d.viaGetter; d.viaLazy }
println(d.reads)Вывод:
4lateinit var объявляет ненулевое свойство, которому присваивается значение позже, после создания объекта, например методом настройки. Чтение свойства до присваивания значения вызывает исключение, а ::name.isInitialized проверяет, было ли ему присвоено значение:
class Screen {
lateinit var title: String
fun load(t: String) { title = t }
fun ready() = ::title.isInitialized
}Внутри main:
val s = Screen()
println(s.ready())
s.load("Home")
println(s.ready())
println(s.title)Результат:
false
true
HomeПредпочитайте обычную инициализацию, если значение известно при создании. Используйте lazy для затратного val, который может не понадобиться, а lateinit — только для var, значение которого действительно появляется позже; lateinit не работает с Int, Boolean и другими примитивными типами.
val config by lazy { loadConfig() } // вычисляется при первом использовании, один раз
lateinit var user: User // присваивается после создания
// lateinit var count: Int // error: не допускается для примитивных типовЗадание
ЛегкоЗавершите класс Document(val text: String). Добавьте wordCount как свойство lazy, которое подсчитывает слова (разделённые одиночными пробелами) и фиксирует каждое вычисление, добавляя 1 к computations, а также lateinit var author: String с методом credit(), который возвращает by Ada или by unknown, если автор не был задан.
Предоставленный код считывает текст, трижды считывает wordCount, задаёт автора, если присутствует вторая строка, и выводит words 5, computed 1, by Ada.
Ваш код должен находиться в Document.kt. В Main.kt содержится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
fun main() {
// Предоставленный код ввода/вывода: оставьте его как есть
val input = generateSequence(::readLine).toList()
val doc = Document(input[0])
val reads = List(3) { doc.wordCount }
val words = reads.first()
if (input.size > 1) doc.author = input[1]
println("words $words, computed ${doc.computations}, ${doc.credit()}")
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Классы и объекты
Работа с файламиОпределение классовПервичные конструкторыБлоки init и валидацияВторичные конструкторыПовторение — читательский билет4Наследование
Открытые классы и подклассыПереопределение членовsuper и конструкторыАбстрактные классыПовторение — каталог сотрудников7Специальные классы
Классы данныхКлассы перечисленийЗапечатанные иерархииequals, hashCode, toStringПовторение — трекер заказов10Паттерны проектирования. Часть 2
Делегирование с помощью byПаттерн декораторПаттерн строительПаттерн состояние2Свойства и инкапсуляция
Пользовательские аксессорыМодификаторы видимостиПриватные сеттерыlazy и lateinitПовторение — банковский счёт5Интерфейсы
Объявление интерфейсовМетоды по умолчаниюМножественные интерфейсыИнтерфейсы как типыПовторение — способы оплаты8Обобщения
Обобщённые функцииОбобщённые классыОграничения типовВариативность с in и outПовторение — очередь с приоритетом11Проект: Управление библиотекой
Книги и читателиВыдача книг3Объекты и компаньоны
Объявления объектовОбъекты-компаньоныКонстанты с constОбъектные выраженияПовторение — билетная касса6Полиморфизм
Динамическая диспетчеризацияПроверка типов и умные приведения типовwhen с типамиФункции-расширенияПовторение — смотритель зоопарка9Паттерны проектирования. Часть 1
Паттерн «Одиночка»Фабричный паттернПаттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Песочница Kotlin