Menu
Coddy logo textTech

Clases abiertas y subclases

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

La herencia permite que una clase se base en otra. La subclase obtiene todas las propiedades y métodos de su superclase y puede añadir los suyos propios. Las clases de Kotlin están cerradas de forma predeterminada, por lo que una clase debe marcarse como open antes de que otra clase pueda extenderla:

open class Animal(val name: String) {
    fun describe() = "$name is an animal"
}

class Dog(name: String) : Animal(name) {
    fun fetch() = "$name fetches the ball"
}

Dentro de main:

val rex = Dog("Rex")
println(rex.describe())
println(rex.fetch())

Salida:

Rex is an animal
Rex fetches the ball

class Dog(name: String) : Animal(name) indica que Dog extiende Animal y pasa name al constructor de la superclase. El parámetro no tiene val, porque la propiedad ya existe en Animal. Una clase que no es open no puede extenderse:

class Plant(val name: String)
// class Tree(name: String) : Plant(name)   // error: este tipo es final, por lo que no se puede extender

open class Vehicle(val wheels: Int)
class Bike : Vehicle(2)                     // pasa un valor fijo
class Truck(val load: Int) : Vehicle(6)     // añade su propia propiedad

Un Dog es un Animal, por lo que una instancia de la subclase puede utilizarse donde se espera el tipo de la superclase. Una List<Animal> puede contener perros, gatos y animales comunes, y cada elemento tiene los miembros de Animal:

open class Animal(val name: String) {
    fun describe() = "$name is an animal"
}
class Dog(name: String) : Animal(name)
class Cat(name: String, val indoor: Boolean) : Animal(name)

Dentro de main:

val pets: List<Animal> = listOf(Dog("Rex"), Cat("Tom", true), Animal("Generic"))
for (p in pets) println(p.describe())

Salida:

Rex is an animal
Tom is an animal
Generic is an animal

La herencia modela una relación es-un: un perro es un animal, una cuenta de ahorros es una cuenta. Cuando una clase solo usa otra (un coche tiene un motor), asígnale en su lugar una propiedad de ese tipo. Las clases cerradas son las predeterminadas de Kotlin, por lo que una clase destinada a la extensión lo indica con open, y todas las demás clases mantienen su comportamiento protegido de las subclases.

open class Account(val owner: String)
class SavingsAccount(owner: String) : Account(owner)   // is-a: herencia

class Engine(val horsepower: Int)
class Car(val engine: Engine)                          // has-a: una propiedad
challenge icon

Desafío

Fácil

Manager repite lo que Employee ya tiene. Haz que Employee sea abierta y convierte Manager en su subclase: Manager(name: String, salary: Int) pasa ambos valores a Employee y conserva solo lo nuevo, una lista privada de nombres de subordinados con addReport(name) y teamSize(). En Employee, raise(percent) aumenta el salario en ese porcentaje, redondeando hacia abajo, y describe() devuelve Ada earns 5500.

El código proporcionado crea un gerente a partir de la primera línea (name,salary), añade cada nombre posterior como subordinado, aplica un aumento del 10 % e imprime Ada earns 5500 and leads 2; después comprueba que un gerente es un Employee.

Tu código va en Employee.kt y Manager.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()
    val (name, salary) = input[0].split(",")
    val boss = Manager(name, salary.toInt())
    for (report in input.drop(1)) boss.addReport(report)
    boss.raise(10)
    println("${boss.describe()} and leads ${boss.teamSize()}")
    println("a manager is an employee: ${(boss as Any) is Employee}")
}
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