Sobrescrevendo Membros
Parte da seção Programação Orientada a Objetos do Journey de Kotlin da Coddy. Lição 18 de 57.
Uma subclasse pode substituir um método herdado pela sua própria versão. A superclasse marca o método como open, e a subclasse o declara novamente com override:
open class Animal(val name: String) {
open fun sound() = "..."
}
class Dog(name: String) : Animal(name) {
override fun sound() = "Woof"
}
class Cat(name: String) : Animal(name) {
override fun sound() = "Meow"
}Dentro de main:
println(Dog("Rex").sound())
println(Cat("Tom").sound())
println(Animal("Generic").sound())Saída:
Woof
Meow
...A versão que é executada é escolhida pela classe real do objeto, mesmo quando o tipo da variável é a superclasse. O código dentro da superclasse que chama um método aberto também obtém a versão da subclasse:
open class Animal(val name: String) {
open fun sound() = "..."
fun speak() = "$name says ${sound()}"
}
class Dog(name: String) : Animal(name) {
override fun sound() = "Woof"
}Dentro de main:
val pets: List<Animal> = listOf(Dog("Rex"), Animal("Generic"))
for (p in pets) println(p.speak())Saída:
Rex says Woof
Generic says ...As propriedades podem ser sobrescritas da mesma forma: open val na superclasse, override val na subclasse, seja como uma propriedade normal, uma propriedade do construtor ou um getter computado:
open class Shape {
open val name = "shape"
open val corners = 0
}
class Triangle : Shape() {
override val name = "triangle"
override val corners = 3
}
class Polygon(override val corners: Int) : Shape() {
override val name: String
get() = "$corners-gon"
}Dentro de main:
for (s in listOf(Shape(), Triangle(), Polygon(6))) println("${s.name}: ${s.corners}")Saída:
shape: 0
triangle: 3
6-gon: 6Um membro marcado como override é aberto novamente, portanto uma subclasse da subclasse pode substituí-lo mais uma vez; final override impede isso. Um membro sem open não pode ser substituído de forma alguma, e uma subclasse não pode declarar um membro com a mesma assinatura:
open class Animal {
open fun sound() = "..."
fun sleep() = "zzz"
}
open class Dog : Animal() {
final override fun sound() = "Woof"
}
class Puppy : Dog() {
// override fun sound() = "Yip" // erro: 'sound' em 'Dog' é final
// fun sleep() = "nap" // erro: 'sleep' oculta um membro da superclasse
}Desafio
FácilAnimal tem legs() (4), sound() (...) e describe(), que retorna Rex has 4 legs and says Woof, construído a partir de legs() e sound(). Torne legs() e sound() sobrescritos e complete as subclasses sobrescrevendo apenas esses dois métodos: Dog diz Woof, Bird tem 2 pernas e diz Tweet, e Snake tem 0 pernas e diz Hiss. describe() permanece como está em Animal.
O código fornecido lê linhas dog,Rex, bird,Pip, snake,Kaa ou qualquer outro tipo (um Animal simples), armazena os animais em uma única List<Animal> e imprime describe() para cada um.
Seu código deve ficar em Animal.kt, Dog.kt, Bird.kt e Snake.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 animals = mutableListOf<Animal>()
for (line in input) {
val (kind, name) = line.split(",")
animals.add(when (kind) {
"dog" -> Dog(name)
"bird" -> Bird(name)
"snake" -> Snake(name)
else -> Animal(name)
})
}
for (a in animals) println(a.describe())
}
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