Menu
Coddy logo textTech

Bloques init y validación

Parte de la sección Programación orientada a objetos del Journey de Kotlin de Coddy. Lección 4 de 57.

Un bloque init se ejecuta cuando se crea una instancia, justo después de asignar los parámetros del constructor. Es el lugar para colocar código de configuración que no cabe en una sola declaración de propiedad:

class Order(val id: Int, items: List<Int>) {
    val total: Int
    val count: Int

    init {
        total = items.sum()
        count = items.size
        println("created order $id")
    }
}

Dentro de main:

val o = Order(7, listOf(4, 6, 10))
println("${o.count} items, total ${o.total}")

Salida:

created order 7
3 items, total 20

require(condition) { message } comprueba un argumento y lanza IllegalArgumentException con el mensaje cuando es falso. Ponerlo en init significa que nunca se puede crear una instancia no válida:

class Percentage(val value: Int) {
    init {
        require(value in 0..100) { "percentage must be 0-100, was $value" }
    }
}

Dentro de main:

println(Percentage(42).value)
try {
    Percentage(150)
} catch (e: IllegalArgumentException) {
    println(e.message)
}

Salida:

42
percentage must be 0-100, was 150

Una clase puede tener varios bloques init; se ejecutan en orden, junto con los inicializadores de propiedades, de arriba abajo:

class Demo(name: String) {
    val first = "first: $name".also { println(it) }

    init { println("init 1") }

    val second = "second".also { println(it) }

    init { println("init 2") }
}

Dentro de main:

Demo("x")
println("done")

Salida:

first: x
init 1
second
init 2
done

La validación en init mantiene la regla junto a los datos. El código que recibe una instancia puede confiar en ella sin comprobarla de nuevo:

class Email(val address: String) {
    init {
        require("@" in address) { "not an email: $address" }
    }
}
fun send(to: Email) { /* no es necesario comprobar la dirección de nuevo */ }
challenge icon

Desafío

Fácil

Completa la clase Password. Su bloque init comprueba, mediante require, que el texto tenga al menos 8 caracteres (mensaje too short) y contenga un dígito (mensaje needs a digit), en ese orden. La propiedad strength se calcula en init: strong cuando el texto también contiene una letra mayúscula; en caso contrario, ok.

El código proporcionado crea un Password para cada línea de entrada e imprime strength o el mensaje de error.

Tu código debe ir en Password.kt. Main.kt contiene el código proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

fun main() {
    // Código de entrada/salida suministrado: déjalo tal como está
    val input = generateSequence(::readLine).toList()
    for (line in input) {
        try {
            println(Password(line).strength)
        } catch (e: IllegalArgumentException) {
            println(e.message)
        }
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Playground de Kotlin