In dit artikel leer je over overerving. Meer specifiek, wat is overerving en hoe het in Kotlin te implementeren (met behulp van voorbeelden).
Overerving is een van de belangrijkste kenmerken van objectgeoriënteerd programmeren. Hiermee kan de gebruiker een nieuwe klasse (afgeleide klasse) maken van een bestaande klasse (basisklasse).
De afgeleide klasse erft alle kenmerken van de basisklasse en kan zelf aanvullende kenmerken hebben.
Voordat we ingaan op de details over de overerving van Kotlin, raden we u aan deze twee artikelen te lezen:
- Kotlin-klasse en objecten
- Kotlin primaire constructeur
Waarom overerving?
Stel dat u in uw aanvraag drie karakters wilt: een wiskundeleraar , een voetballer en een zakenman .
Omdat alle personages personen zijn, kunnen ze lopen en praten. Ze hebben echter ook een aantal speciale vaardigheden. Een wiskundeleraar kan wiskunde geven , een voetballer kan voetballen en een zakenman kan een bedrijf runnen .
U kunt individueel drie klassen creëren die kunnen lopen, praten en hun speciale vaardigheid kunnen uitvoeren.
In elk van de lessen zou je voor elk personage dezelfde code voor lopen en praten kopiëren.
Als je een nieuwe functie wilt toevoegen - eat, moet je voor elk teken dezelfde code implementeren. Dit kan gemakkelijk foutgevoelig worden (bij het kopiëren) en dubbele codes.
Het zou een stuk gemakkelijker zijn als we een Person
klas hadden met basisfuncties zoals praten, lopen, eten, slapen en speciale vaardigheden toevoegen aan die functies volgens onze personages. Dit gebeurt met overerving.
Met behulp van de erfenis, nu heb je niet dezelfde code te implementeren walk()
, talk()
en eat()
voor elke klasse. Je moet ze gewoon erven .
Dus voor MathTeacher
(afgeleide klasse), erft u alle kenmerken van een Person
(basisklasse) en voegt u een nieuwe functie toe teachMath()
. Evenzo ervaar je voor de Footballer
klas alle kenmerken van de Person
klas en voeg je een nieuwe functie toe playFootball()
, enzovoort.
Dit maakt uw code schoner, begrijpelijker en uitbreidbaar.
Het is belangrijk om te onthouden: wanneer u met overerving werkt, moet elke afgeleide klasse voldoen aan de voorwaarde of het "een" basisklasse is of niet. In het bovenstaande voorbeeld MathTeacher
is a Person
, Footballer
is a Person
. Je kunt zoiets niet hebben als, Businessman
is een Business
.
Kotlin erfenis
Laten we proberen de bovenstaande discussie in code te implementeren:
open klas Persoon (leeftijd: Int) (// code voor eten, praten, lopen) klas Math Leraar (leeftijd: Int): Persoon (leeftijd) (// andere kenmerken van wiskundeleraar) klas Voetballer (leeftijd: Int): Persoon ( leeftijd) (// andere kenmerken van voetballer) klasse Zakenman (leeftijd: Int): Persoon (leeftijd) (// andere kenmerken van zakenman)
Hier, Person
is een basisklasse, en klassen MathTeacher
, Footballer
en Businessman
zijn afgeleid van de klasse persoon.
Let op, het sleutelwoord open
voor de basisklasse Person
. Het is belangrijk.
De lessen in Kotlin zijn standaard definitief. Als u bekend bent met Java, weet u dat een laatste klasse niet kan worden onderverdeeld. Door de open annotatie op een klasse te gebruiken, kunt u met de compiler er nieuwe klassen uit afleiden.
Voorbeeld: Kotlin Inheritance
open class Person(age: Int, name: String) ( init ( println("My name is $name.") println("My age is $age") ) ) class MathTeacher(age: Int, name: String): Person(age, name) ( fun teachMaths() ( println("I teach in primary school.") ) ) class Footballer(age: Int, name: String): Person(age, name) ( fun playFootball() ( println("I play for LA Galaxy.") ) ) fun main(args: Array) ( val t1 = MathTeacher(25, "Jack") t1.teachMaths() println() val f1 = Footballer(29, "Christiano") f1.playFootball() )
Wanneer u het programma uitvoert, is de uitvoer:
Mijn naam is Jack. Mijn leeftijd is 25. Ik geef les op de basisschool. Mijn naam is Cristiano. Mijn leeftijd is 29. Ik speel voor LA Galaxy.
Hier twee klassen MathTeacher
en Footballer
zijn afgeleid van de Person
klasse.
De primaire constructor van de Person
klasse heeft twee eigenschappen gedeclareerd: leeftijd en naam, en het heeft een initialisatieblok. Het startblok (en lidfuncties) van de basisklasse Person
is toegankelijk voor de objecten van afgeleide klassen ( MathTeacher
en Footballer
).
Afgeleide klassen MathTeacher
en Footballer
hebben hun eigen lidfuncties teachMaths()
en playFootball()
respectievelijk. Deze functies zijn alleen toegankelijk vanuit de objecten van hun respectievelijke klasse.
Wanneer het object t1 van MathTeacher
klasse is gemaakt,
val t1 = MathTeacher (25; "Jack")
De parameters worden doorgegeven aan de primaire constructor. In Kotlin wordt init
blok aangeroepen wanneer het object wordt gemaakt. Omdat, MathTeacher
is afgeleid van Person
class, zoekt het naar initialisatieblok in de basisklasse (Person) en voert het uit. Als het MathTeacher
init-blok had, zou de compiler ook het init-blok van de afgeleide klasse hebben uitgevoerd.
Vervolgens wordt de teachMaths()
functie voor object t1
aangeroepen met behulp van t1.teachMaths()
statement.
Het programma werkt op dezelfde manier als object f1
van de Footballer
klasse wordt gemaakt. Het voert het init-blok van de basisklasse uit. Vervolgens wordt de class- playFootball()
methode Footballer
aangeroepen met statement f1.playFootball()
.
Belangrijke opmerkingen: Kotlin Inheritance
- Als de klasse een primaire constructor heeft, moet de basis worden geïnitialiseerd met de parameters van de primaire constructor. In het bovenstaande programma hebben beide afgeleide klassen twee parameters
age
enname
, en beide parameters worden geïnitialiseerd in de primaire constructor in de basisklasse.
Hier is nog een voorbeeld:open class Person(age: Int, name: String) ( // some code ) class Footballer(age: Int, name: String, club: String): Person(age, name) ( init ( println("Football player $name of age $age and plays for $club.") ) fun playFootball() ( println("I am playing football.") ) ) fun main(args: Array) ( val f1 = Footballer(29, "Cristiano", "LA Galaxy") )
- In het geval dat er geen primaire constructor is, moet elke basisklasse de basis initialiseren (met behulp van het super-sleutelwoord) of delegeren aan een andere constructor die dat doet. Bijvoorbeeld,
fun main(args: Array) ( val p1 = AuthLog("Bad Password") ) open class Log ( var data: String = "" var numberOfData = 0 constructor(_data: String) ( ) constructor(_data: String, _numberOfData: Int) ( data = _data numberOfData = _numberOfData println("$data: $numberOfData times") ) ) class AuthLog: Log ( constructor(_data: String): this("From AuthLog -> + $_data", 10) ( ) constructor(_data: String, _numberOfData: Int): super(_data, _numberOfData) ( ) )
Functies en eigenschappen van leden overschrijven
If the base class and the derived class contains a member function (or property) with the same name, you can need to override the member function of the derived class using override
keyword, and use open
keyword for the member function of the base class.
Example: Overriding Member Function
// Empty primary constructor open class Person() ( open fun displayAge(age: Int) ( println("My age is $age.") ) ) class Girl: Person() ( override fun displayAge(age: Int) ( println("My fake age is $(age - 5).") ) ) fun main(args: Array) ( val girl = Girl() girl.displayAge(31) )
When you run the program, the output will be:
My fake age is 26.
Here, girl.displayAge(31)
calls the displayAge()
method of the derived class Girl
.
You can override property of the base class in similar way.
Visit how Kotlin getters and setters work in Kotlin before you check the example below.
// Empty primary constructor open class Person() ( open var age: Int = 0 get() = field set(value) ( field = value ) ) class Girl: Person() ( override var age: Int = 0 get() = field set(value) ( field = value - 5 ) ) fun main(args: Array) ( val girl = Girl() girl.age = 31 println("My fake age is $(girl.age).") )
When you run the program, the output will be:
My fake age is 26.
As you can see, we have used override
and open
keywords for age property in derived class and base class respectively.
Calling Members of Base Class from Derived Class
U kunt functies (en toegangseigenschappen) van de basisklasse aanroepen vanuit een afgeleide klasse met behulp van super
trefwoord. Hier is hoe:
open class Person() ( open fun displayAge(age: Int) ( println("My actual age is $age.") ) ) class Girl: Person() ( override fun displayAge(age: Int) ( // calling function of base class super.displayAge(age) println("My fake age is $(age - 5).") ) ) fun main(args: Array) ( val girl = Girl() girl.displayAge(31) )
Wanneer u het programma uitvoert, is de uitvoer:
Mijn leeftijd is 31. Mijn nepleeftijd is 26.