Ridefinizione dei membri
Fa parte della sezione Programmazione orientata agli oggetti del percorso Kotlin di Coddy. Lezione 18 di 57.
Una sottoclasse può sostituire un metodo ereditato con una propria versione. La superclasse contrassegna il metodo come open e la sottoclasse lo dichiara di nuovo con 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"
}All'interno di main:
println(Dog("Rex").sound())
println(Cat("Tom").sound())
println(Animal("Generic").sound())Output:
Woof
Meow
...La versione eseguita viene scelta in base alla classe effettiva dell'oggetto, anche quando il tipo della variabile è la superclasse. Anche il codice all'interno della superclasse che chiama un metodo aperto ottiene la versione della sottoclasse:
open class Animal(val name: String) {
open fun sound() = "..."
fun speak() = "$name says ${sound()}"
}
class Dog(name: String) : Animal(name) {
override fun sound() = "Woof"
}All'interno di main:
val pets: List<Animal> = listOf(Dog("Rex"), Animal("Generic"))
for (p in pets) println(p.speak())Output:
Rex says Woof
Generic says ...Anche le proprietà possono essere sottoposte a override allo stesso modo: open val nella superclasse, override val nella sottoclasse, come proprietà normale, proprietà del costruttore o getter calcolato:
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"
}All'interno di main:
for (s in listOf(Shape(), Triangle(), Polygon(6))) println("${s.name}: ${s.corners}")Output:
shape: 0
triangle: 3
6-gon: 6Un membro contrassegnato con override è di nuovo aperto, quindi una sottoclasse della sottoclasse può sovrascriverlo ancora una volta; final override lo impedisce. Un membro senza open non può essere sovrascritto in alcun modo e una sottoclasse non può dichiarare un membro con la stessa firma:
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" // errore: 'sound' in 'Dog' è final
// fun sleep() = "nap" // errore: 'sleep' nasconde un membro della superclasse
}Sfida
FacileAnimal ha legs() (4), sound() (...) e describe(), che restituisce Rex has 4 legs and says Woof, composto da legs() e sound(). Rendi sovrascrivibili legs() e sound() e completa le sottoclassi sovrascrivendo solo questi due metodi: Dog dice Woof, Bird ha 2 zampe e dice Tweet e Snake ha 0 zampe e dice Hiss. describe() resta com'è in Animal.
Il codice fornito legge righe dog,Rex, bird,Pip, snake,Kaa o di qualsiasi altro tipo (un semplice Animal), memorizza gli animali in un'unica List<Animal> e stampa describe() per ciascuno.
Il tuo codice va in Animal.kt, Dog.kt, Bird.kt e Snake.kt. Main.kt contiene il codice fornito per input/output e non può essere modificato.
Provalo tu
fun main() {
// Codice di input/output fornito: lascialo così com'è
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())
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Classi e oggetti
Lavorare con i fileDefinire le classiCostruttori primariBlocchi init e convalidaCostruttori secondariRiepilogo - Tessera della biblioteca4Ereditarietà
Classi aperte e sottoclassiRidefinizione dei membrisuper e costruttoriClassi astratteRiepilogo - Elenco del personale2Proprietà e incapsulamento
Accessor personalizzatiModificatori di visibilitàSetter privatilazy e lateinitRipasso - Conto bancario5Interfacce
Dichiarare le interfacceMetodi predefinitiInterfacce multipleLe interfacce come tipiRiepilogo - Metodi di pagamento8Tipi generici
Funzioni genericheClassi genericheVincoli sui tipiVarianza con in e outRiepilogo - Coda con priorità11Progetto: Gestione della biblioteca
Libri e sociPrendere in prestito i libriEsercitati da solo: Playground Kotlin