Constantes com const
Parte da seção Programação Orientada a Objetos do Journey de Kotlin da Coddy. Lição 14 de 57.
const val declara uma constante em tempo de compilação: um valor fixado quando o programa é compilado. Ela é permitida no nível superior de um arquivo e dentro de um object ou companion object, e somente para tipos básicos como Int, Double e Boolean, e para String:
const val MAX_PLAYERS = 4
class Lobby {
val players = mutableListOf<String>()
fun canStart() = players.size in MIN_PLAYERS..MAX_PLAYERS
companion object {
const val MIN_PLAYERS = 2
}
}Dentro de main:
val lobby = Lobby()
lobby.players += listOf("ada", "bo")
println(lobby.canStart())
println("${Lobby.MIN_PLAYERS}-$MAX_PLAYERS players")Saída:
true
2-4 playersAs constantes são nomeadas em UPPER_SNAKE_CASE. const é mais restrito que val: o valor deve ser conhecido sem executar nenhum código, portanto uma chamada de função ou uma lista não é permitida. Um val em um objeto também é compartilhado e somente leitura, além de aceitar qualquer valor:
const val GREETING = "Hello" // um literal String
const val TIMEOUT_MS = 30 * 1000 // calculado a partir de literais
// const val START = System.nanoTime() // erro: não é uma constante
// const val DAYS = listOf("Mon", "Tue") // erro: apenas tipos básicos e String
object Defaults {
val DAYS = listOf("Mon", "Tue") // um val compartilhado somente leitura
}Um objeto companion também pode conter estado mutável compartilhado. Cada instância lê e altera a mesma propriedade, o que é adequado para contadores e caches. Esta classe mantém uma instância por nome, portanto, solicitar duas vezes retorna o mesmo objeto (=== verifica se duas referências apontam para um único objeto):
class Tile private constructor(val name: String) {
companion object {
private val cache = mutableMapOf<String, Tile>()
val created: Int
get() = cache.size
fun of(name: String) = cache.getOrPut(name) { Tile(name) }
}
}Dentro de main:
val a = Tile.of("grass")
val b = Tile.of("grass")
Tile.of("water")
println(a === b)
println(Tile.created)Saída:
true
2Nível superior ou companion? Uma constante ou função de nível superior pertence ao seu arquivo e é usada pelo seu nome simples em todos os arquivos do pacote. Coloque uma constante em um companion quando ela pertencer a uma classe: os chamadores escrevem Lobby.MIN_PLAYERS, o que indica de onde o valor vem, e um private const val permanece dentro dessa classe.
// Limits.kt
const val MAX_UPLOAD_MB = 25 // usado em todos os lugares como MAX_UPLOAD_MB
// Lobby.kt
class Lobby {
companion object {
const val MIN_PLAYERS = 2 // usado como Lobby.MIN_PLAYERS
private const val ROOM_PREFIX = "L-" // apenas dentro de Lobby
}
}Desafio
FácilComplete a classe Order(val item: String, val qty: Int). Seu objeto companion contém as constantes MAX_QTY = 10 e PREFIX = "ORD", um contador privado para o próximo número do pedido, o total compartilhado somente para leitura totalItems e a count calculada dos pedidos criados. O bloco init exige uma quantidade entre 1 e MAX_QTY com a mensagem quantity must be 1-10 (construída a partir da constante), depois atribui ao pedido seu id ORD-001, ORD-002, ... e adiciona sua quantidade a totalItems. label() retorna ORD-001 tea x2.
O código fornecido imprime max per order: 10, depois lê as linhas tea 2 e imprime o rótulo ou a mensagem de erro e, por fim, orders: 2, items: 5. Pedidos recusados não consomem um número.
Seu código deve ficar em Order.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()
println("max per order: ${Order.MAX_QTY}")
for (line in input) {
val (item, qty) = line.split(" ")
try {
println(Order(item, qty.toInt()).label())
} catch (e: IllegalArgumentException) {
println(e.message)
}
}
println("orders: ${Order.count}, items: ${Order.totalItems}")
}
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 Livros3Objetos e Companheiros
Declarações de ObjetosObjetos CompanionConstantes com constExpressões de ObjetosRevisão - BilheteriaPratique por conta própria: Playground de Kotlin