lazy e lateinit
Parte da seção Programação Orientada a Objetos do Journey de Kotlin da Coddy. Lição 10 de 57.
by lazy { ... } adia o cálculo de um val até que ele seja lido pela primeira vez e, então, memoriza o resultado. É adequado para valores que são custosos ou nem sempre necessários:
class Report(val rows: List<Int>) {
val summary: String by lazy {
println("computing summary")
"total ${rows.sum()}"
}
}Dentro de main:
val r = Report(listOf(3, 4))
println("created")
println(r.summary)
println(r.summary)Saída:
created
computing summary
total 7
total 7O bloco é executado uma vez: a segunda leitura acima usou o resultado armazenado. Diferentemente de um getter personalizado, que é executado em cada leitura, lazy calcula uma vez e armazena em cache:
class Demo {
var reads = 0
val viaGetter: Int
get() { reads++; return 42 }
val viaLazy: Int by lazy { reads++; 42 }
}Dentro de main:
val d = Demo()
repeat(3) { d.viaGetter; d.viaLazy }
println(d.reads)Saída:
4lateinit var declara uma propriedade não nula que é atribuída posteriormente, após a construção, por exemplo, por um método de configuração. Lê-la antes de ser atribuída lança uma exceção, e ::name.isInitialized verifica isso:
class Screen {
lateinit var title: String
fun load(t: String) { title = t }
fun ready() = ::title.isInitialized
}Dentro de main:
val s = Screen()
println(s.ready())
s.load("Home")
println(s.ready())
println(s.title)Saída:
false
true
HomePrefira a inicialização direta quando o valor for conhecido na construção. Use lazy para um val dispendioso que pode não ser necessário, e lateinit somente para um var cujo valor realmente seja definido mais tarde; lateinit não funciona com Int, Boolean ou outros tipos primitivos.
val config by lazy { loadConfig() } // computado no primeiro uso, uma vez
lateinit var user: User // atribuído após a construção
// lateinit var count: Int // erro: não permitido em tipos primitivosDesafio
FácilComplete a classe Document(val text: String). Adicione wordCount como uma propriedade lazy que conta as palavras (separadas por espaços simples) e registra cada cálculo adicionando 1 a computations, e uma lateinit var author: String com um método credit() que retorna by Ada ou by unknown quando o autor não tiver sido definido.
O código fornecido lê o texto, lê wordCount três vezes, define o autor quando uma segunda linha está presente e imprime words 5, computed 1, by Ada.
Seu código deve ser colocado em Document.kt. Main.kt contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
fun main() {
// Código de entrada/saída fornecido: mantenha-o como está
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()}")
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Classes e Objetos
Trabalhando com ArquivosDefinindo ClassesConstrutores PrimáriosBlocos init e ValidaçãoConstrutores SecundáriosRecapitulação - Cartão da Biblioteca4Herança
Classes Abertas e SubclassesSobrescrevendo Membrossuper e ConstrutoresClasses AbstratasRevisão - Diretório de Funcionários2Propriedades e Encapsulamento
Acessores PersonalizadosModificadores de VisibilidadeSetters Privadoslazy e lateinitRevisão - Conta Bancária5Interfaces
Declarando InterfacesMétodos PadrãoMúltiplas InterfacesInterfaces como TiposRecapitulação - Métodos de Pagamento8Genéricos
Funções genéricasClasses genéricasRestrições de tipoVariância com in e outRecapitulação - Fila de prioridade11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Playground de Kotlin