V tomto článku sa dozviete o dedičstve. Konkrétnejšie, čo je to dedičstvo a ako ho implementovať v Kotline (pomocou príkladov).
Dedičnosť je jednou z kľúčových vlastností objektovo orientovaného programovania. Umožňuje užívateľovi vytvoriť novú triedu (odvodenú triedu) z existujúcej triedy (základnej triedy).
Odvodená trieda dedí všetky funkcie od základnej triedy a môže mať ďalšie vlastné vlastnosti.
Pred podrobnosťami o dedičstve Kotlin vám odporúčame prečítať si tieto dva články:
- Kotlinova trieda a objekty
- Kotlin primárny konštruktér
Prečo dedičstvo?
Predpokladajme, že vo svojej žiadosti chcete tri postavy - učiteľa matematiky , futbalistu a podnikateľa .
Pretože všetky postavy sú osoby, môžu chodiť a rozprávať sa. Majú však aj niektoré špeciálne schopnosti. Učiteľ matematiky môže učiť matematiku , futbalista futbal a podnikateľ môže podnikať .
Môžete individuálne vytvoriť tri triedy, ktoré môžu chodiť, rozprávať a vykonávať svoje špeciálne schopnosti.
V každej z tried by ste pre každú postavu kopírovali rovnaký kód pre chôdzu a rozhovor.
Ak chcete pridať novú funkciu - jesť, musíte pre každú postavu implementovať rovnaký kód. Toto sa môže ľahko stať náchylným na chyby (pri kopírovaní) a duplikátom kódov.
Bolo by to oveľa jednoduchšie, keby sme mali Person
triedu so základnými funkciami, ako sú rozprávanie, chôdza, jedlo, spánok a pridávanie ďalších schopností k týmto vlastnostiam podľa našich postáv. To sa deje pomocou dedičstva.
Pomocou dedičnosti, teraz nemusíte implementovať rovnaký kód walk()
, talk()
a eat()
pre každú triedu. Musíte ich len zdediť .
Takže pre MathTeacher
(odvodenú triedu) dedíte všetky vlastnosti Person
(základnej triedy) a pridáte novú funkciu teachMath()
. Rovnako pre Footballer
triedu dedíte všetky funkcie Person
triedy a pridáte novú funkciu playFootball()
atď.
Vďaka tomu je váš kód čistejší, zrozumiteľnejší a rozšíriteľný.
Je dôležité mať na pamäti: Pri práci s dedičstvom by každá odvodená trieda mala spĺňať podmienku, či je „ základnou “ triedou alebo nie. Vo vyššie uvedenom príklade MathTeacher
je a Person
, Footballer
je a Person
. Nemôžete mať niečo ako, Businessman
je Business
.
Kotlinove dedenie
Pokúsme sa implementovať vyššie uvedenú diskusiu do kódu:
otvorená trieda Osoba (vek: Int) (// kód na jedenie, rozprávanie, chôdzu) trieda MathTeacher (vek: Int): Osoba (vek) (// ďalšie vlastnosti učiteľa matematiky) trieda Futbalista (vek: Int): Osoba ( vek) (// ďalšie vlastnosti futbalistu) trieda Podnikateľ (vek: Int): Osoba (vek) (// ďalšie vlastnosti podnikateľa)
Odtiaľ Person
je základnej triedy a triedy MathTeacher
, Footballer
a Businessman
sú odvodené od triedy Person.
Všimnite si, kľúčové slovo open
, než základnej triedy Person
. Je to dôležité.
Predvolene sú triedy v Kotline konečné. Ak ovládate jazyk Java, viete, že poslednú triedu nemožno zaradiť do podtriedy. Pomocou otvorenej anotácie pre triedu vám kompilátor umožňuje odvodiť z nej nové triedy.
Príklad: dedičstvo Kotlin
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() )
Po spustení programu bude výstup:
Moje meno je Jack. Môj vek je 25 rokov, učím na základnej škole. Volám sa Cristiano. Môj vek je 29 rokov, hrám za LA Galaxy.
Tu sú dve triedy MathTeacher
a Footballer
sú odvodené od Person
triedy.
Primárny konštruktor Person
triedy deklaroval dve vlastnosti: vek a meno a má blok inicializátora. K bloku inicializátora (a členským funkciám) základnej triedy Person
je možné pristupovať prostredníctvom objektov odvodených tried ( MathTeacher
a Footballer
).
Odvodené triedy MathTeacher
a Footballer
majú svoje vlastné funkcie členov teachMaths()
a playFootball()
resp. Tieto funkcie sú prístupné iba z objektov príslušnej triedy.
Keď MathTeacher
sa vytvorí objekt t1 triedy,
val t1 = MathTeacher (25, „Jack“)
Parametre sa odovzdajú primárnemu konštruktoru. V Kotline sa init
blok volá, keď je objekt vytvorený. Pretože MathTeacher
je odvodený z Person
triedy, vyhľadá inicializačný blok v základnej triede (Osoba) a vykoná ho. Keby MathTeacher
mal blok init, kompilátor by tiež vykonal blok init odvodenej triedy.
Ďalej sa teachMaths()
funkcia pre objekt t1
volá pomocou t1.teachMaths()
príkazu.
Program funguje podobne aj pri f1
vytváraní objektu Footballer
triedy. Vykoná blok init základnej triedy. Potom sa playFootball()
metóda Footballer
triedy nazýva pomocou príkazu f1.playFootball()
.
Dôležité poznámky: Dedenie Kotlin
- Ak má trieda primárny konštruktor, musí sa základňa inicializovať pomocou parametrov primárneho konštruktora. Vo vyššie uvedenom programe, obe odvodené triedy majú dva parametre
age
aname
, a oba tieto parametre sú inicializované v primárnom konstruktoru v základnej triede.
Tu je ďalší príklad: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") )
- V prípade, že neexistuje primárny konštruktor, musí každá základná trieda inicializovať základňu (pomocou kľúčového slova super) alebo delegovať na iného konštruktora, ktorý to robí. Napríklad,
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) ( ) )
Prepísanie členských funkcií a vlastností
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
Funkcie (a prístup k vlastnostiam) základnej triedy môžete zavolať z odvodenej triedy pomocou super
kľúčového slova. Tu je postup:
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) )
Po spustení programu bude výstup:
Môj vek je 31. Môj falošný vek je 26.