V tomto článku se dozvíte o dědičnosti. Přesněji řečeno, co je to dědičnost a jak ji implementovat v Kotlinu (pomocí příkladů).
Dědičnost je jednou z klíčových vlastností objektově orientovaného programování. Umožňuje uživateli vytvořit novou třídu (odvozenou třídu) z existující třídy (základní třídy).
Odvozená třída dědí všechny funkce od základní třídy a může mít další vlastní funkce.
Před podrobnostmi o dědičnosti Kotlin doporučujeme zkontrolovat tyto dva články:
- Kotlinova třída a objekty
- Kotlin Primární konstruktér
Proč dědictví?
Předpokládejme, že ve své žádosti chcete tři postavy - učitele matematiky , fotbalistu a obchodníka .
Protože všechny postavy jsou osoby, mohou chodit a mluvit. Mají však také některé speciální dovednosti. Učitel matematiky může učit matematiku , fotbalista může hrát fotbal a podnikatel může podnikat .
Můžete individuálně vytvořit tři třídy, které mohou chodit, mluvit a provádět své speciální dovednosti.
V každé z tříd byste kopírovali stejný kód pro procházku a mluvení pro každou postavu.
Pokud chcete přidat novou funkci - jíst, musíte implementovat stejný kód pro každý znak. To může snadno způsobit chyby (při kopírování) a duplicitní kódy.
Bylo by mnohem jednodušší, kdybychom měli Person
třídu se základními funkcemi, jako je mluvení, chůze, jídlo, spánek a přidávání speciálních dovedností k těmto funkcím podle našich postav. To se děje pomocí dědičnosti.
Pomocí dědičnosti, teď nemusíte implementovat stejný kód walk()
, talk()
a eat()
pro každou třídu. Musíte je jen zdědit .
Takže pro MathTeacher
(odvozenou třídu) zdědíte všechny funkce Person
(základní třídy) a přidáte novou funkci teachMath()
. Stejně tak u Footballer
třídy zdědíte všechny funkce Person
třídy a přidáte novou funkci playFootball()
atd.
Díky tomu je váš kód čistší, srozumitelnější a rozšiřitelnější.
Je důležité si pamatovat: Při práci s dědičností by každá odvozená třída měla splňovat podmínku, zda „je“ základní třídou či nikoli. Ve výše uvedeném příkladu MathTeacher
je a Person
, Footballer
je a Person
. Nemůžete mít něco jako, Businessman
je Business
.
Kotlinovo dědictví
Zkusme implementovat výše uvedenou diskusi v kódu:
otevřená třída Osoba (věk: Int) (// kód k jídlu, mluvení, chůzi) třída MathTeacher (věk: Int): Osoba (věk) (// další vlastnosti učitele matematiky) Třída fotbalista (věk: Int): Osoba ( age) (// other features of footballer) class Businessman (age: Int): Person (age) (// other features of businessman)
Odtud Person
je základní třídy a třídy MathTeacher
, Footballer
a Businessman
jsou odvozeny od třídy Person.
Všimněte si, klíčové slovo open
, než základní třídy Person
. Je to důležité.
Ve výchozím nastavení jsou třídy v Kotlin konečné. Pokud znáte Javu, víte, že finální třídu nelze podtřídit. Pomocí otevřené anotace třídy umožňuje kompilátor z ní odvodit nové třídy.
Příklad: Kotlinova dědičnost
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() )
Když spustíte program, výstup bude:
Jmenuji se Jack. Můj věk je 25 let, učím na základní škole. Jmenuji se Cristiano. Můj věk je 29 let, hraji za LA Galaxy.
Zde jsou dvě třídy MathTeacher
a Footballer
jsou odvozeny od Person
třídy.
Primární konstruktor Person
třídy deklaroval dvě vlastnosti: věk a název a má blok inicializátoru. K bloku inicializátoru (a členským funkcím) základní třídy Person
lze přistupovat pomocí objektů odvozených tříd ( MathTeacher
a Footballer
).
Odvozené třídy MathTeacher
a Footballer
mají své vlastní funkce členů teachMaths()
a playFootball()
resp. Tyto funkce jsou přístupné pouze z objektů příslušné třídy.
Když MathTeacher
je vytvořen objekt t1 třídy,
val t1 = MathTeacher (25, „Jack“)
Parametry jsou předány primárnímu konstruktoru. V Kotlin je init
blok vyvolán, když je objekt vytvořen. Vzhledem k tomu, že MathTeacher
je odvozen od Person
třídy, hledá blok inicializátoru v základní třídě (Person) a provede jej. Pokud by MathTeacher
měl blok init, kompilátor by také provedl blok init odvozené třídy.
Dále se teachMaths()
funkce pro objekt t1
nazývá pomocí t1.teachMaths()
příkazu.
Program funguje podobně jako když objekt f1
ze Footballer
je vytvořen třídy. Spustí blok init základní třídy. Potom se playFootball()
metoda Footballer
třídy nazývá pomocí příkazu f1.playFootball()
.
Důležité poznámky: Dědičnost Kotlin
- If the class has a primary constructor, the base must be initialized using the parameters of the primary constructor. In the above program, both derived classes have two parameters
age
andname
, and both these parameters are initialized in primary constructor in the base class.
Here's another example: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 case of no primary constructor, each base class has to initialize the base (using super keyword), or delegate to another constructor which does that. For example,
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) ( ) )
Overriding Member Functions and Properties
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
Můžete volat funkce (a přistupovat k vlastnostem) základní třídy z odvozené třídy pomocí super
klíčového slova. Zde 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) )
Když spustíte program, výstup bude:
Můj věk je 31. Můj falešný věk je 26.