Classes Abertas e Subclasses
Parte da seção Programação Orientada a Objetos do Journey de Kotlin da Coddy. Lição 17 de 57.
Herança permite que uma classe se baseie em outra. A subclasse recebe todas as propriedades e métodos da sua superclasse e pode adicionar os seus próprios. As classes Kotlin são fechadas por padrão, portanto uma classe precisa ser marcada como open antes que outra classe possa estendê-la:
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())Saída:
Rex is an animal
Rex fetches the ballclass Dog(name: String) : Animal(name) indica que Dog estende Animal e passa name para o construtor da superclasse. O parâmetro não tem val, porque a propriedade já existe em Animal. Uma classe que não é open não pode ser estendida:
class Plant(val name: String)
// class Tree(name: String) : Plant(name) // erro: este tipo é final, então não pode ser estendido
open class Vehicle(val wheels: Int)
class Bike : Vehicle(2) // passa um valor fixo
class Truck(val load: Int) : Vehicle(6) // adiciona sua própria propriedadeUm Dog é um Animal, portanto uma instância de uma subclasse pode ser usada sempre que o tipo da superclasse for esperado. Uma List<Animal> pode armazenar cães, gatos e animais comuns, e cada elemento tem os membros 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())Saída:
Rex is an animal
Tom is an animal
Generic is an animalA herança modela uma relação is-a: um cachorro é um animal, uma conta poupança é uma conta. Quando uma classe apenas usa outra (um carro tem um motor), dê a ela uma propriedade desse tipo. Classes fechadas são o padrão do Kotlin, de modo que uma classe destinada à extensão indica isso com open, e todas as outras classes mantêm seu comportamento protegido de subclasses.
open class Account(val owner: String)
class SavingsAccount(owner: String) : Account(owner) // is-a: herança
class Engine(val horsepower: Int)
class Car(val engine: Engine) // has-a: uma propriedadeDesafio
FácilManager repete o que Employee já possui. Torne Employee aberta e transforme Manager em sua subclasse: Manager(name: String, salary: Int) passa os dois valores para Employee e mantém apenas o que é novo, uma lista privada de nomes dos subordinados com addReport(name) e teamSize(). Em Employee, raise(percent) aumenta o salário por essa porcentagem, arredondando para baixo, e describe() retorna Ada earns 5500.
O código fornecido cria um gerente a partir da primeira linha (name,salary), adiciona cada nome seguinte como subordinado, dá um aumento de 10% e imprime Ada earns 5500 and leads 2, então verifica se um gerente é um Employee.
Seu código deve estar em Employee.kt e Manager.kt. Main.kt contém o código de entrada/saída fornecido 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 (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}")
}
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