Dziedziczenie Kotlin (z przykładami)

Z tego artykułu dowiesz się o dziedziczeniu. Dokładniej, czym jest dziedziczenie i jak je zaimplementować w Kotlinie (na przykładach).

Dziedziczenie jest jedną z kluczowych cech programowania obiektowego. Pozwala użytkownikowi na utworzenie nowej klasy (klasy pochodnej) z istniejącej klasy (klasy bazowej).

Klasa pochodna dziedziczy wszystkie funkcje z klasy bazowej i może mieć własne dodatkowe funkcje.

Zanim przejdziemy do szczegółów dotyczących dziedziczenia Kotlin, zalecamy zapoznanie się z tymi dwoma artykułami:

  • Klasa Kotlin i obiekty
  • Główny konstruktor Kotlin

Dlaczego dziedziczenie?

Załóżmy, że w swojej aplikacji potrzebujesz trzech postaci - nauczyciela matematyki , piłkarza i biznesmena .

Ponieważ wszystkie postacie są osobami, mogą chodzić i mówić. Jednak mają też specjalne umiejętności. Nauczyciel matematyki może uczyć matematyki , piłkarz może grać w piłkę nożną, a biznesmen może prowadzić biznes .

Możesz indywidualnie stworzyć trzy klasy, które mogą chodzić, rozmawiać i wykonywać swoje specjalne umiejętności.

Na każdej z klas kopiowałbyś ten sam kod na spacer i rozmowę dla każdej postaci.

Jeśli chcesz dodać nową funkcję - jeść, musisz zaimplementować ten sam kod dla każdego znaku. Może to łatwo stać się podatne na błędy (podczas kopiowania) i zduplikować kody.

Byłoby o wiele łatwiej, gdybyśmy mieli Personklasę z podstawowymi funkcjami, takimi jak rozmowa, chodzenie, jedzenie, spanie i dodawanie specjalnych umiejętności do tych funkcji, zgodnie z naszymi postaciami. Odbywa się to za pomocą dziedziczenia.

Korzystanie z dziedziczenia, teraz nie realizują ten sam kod walk(), talk()a eat()dla każdej klasy. Musisz je tylko odziedziczyć .

Tak więc w przypadku MathTeacher(klasa pochodna) dziedziczysz wszystkie funkcje Person(klasy bazowej) i dodajesz nową funkcję teachMath(). Podobnie w przypadku Footballerklasy dziedziczysz wszystkie cechy Personklasy, dodajesz nową funkcję playFootball()i tak dalej.

Dzięki temu Twój kod jest czystszy, zrozumiały i rozszerzalny.

Ważne jest, aby pamiętać: podczas pracy z dziedziczeniem każda klasa pochodna powinna spełniać warunek, czy „jest” klasą bazową, czy nie. W powyższym przykładzie MathTeacher to a Person , Footballer to a Person . Nie możesz mieć czegoś takiego jak, Businessman jest Business .

Dziedziczenie Kotlin

Spróbujmy zaimplementować powyższą dyskusję w kodzie:

 klasa otwarta Osoba (wiek: Int) (// kod do jedzenia, mówienia, chodzenia) klasa MathTeacher (wiek: Int): Osoba (wiek) (// inne cechy nauczyciela matematyki) klasa Piłkarz (wiek: Int): Osoba ( wiek) (// inne cechy piłkarza) klasa Przedsiębiorca (wiek: Int): Osoba (wiek) (// inne cechy biznesmena)

Tutaj Personjest klasą bazową, a zajęcia MathTeacher, Footballeri Businessmanpochodzą z klasy Person.

Wskazówki, słowo openzanim klasy bazowej Person. To ważne.

Domyślnie zajęcia w Kotlinie są ostateczne. Jeśli znasz język Java, wiesz, że klasy końcowej nie można podklasy. Korzystając z otwartej adnotacji w klasie, kompilator umożliwia tworzenie z niej nowych klas.

Przykład: Dziedziczenie 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 uruchomieniu programu wynik będzie następujący:

Mam na imię Jack. Mam 25 lat i uczę w szkole podstawowej. Mam na imię Cristiano. Mam 29 lat, gram w LA Galaxy.

Tutaj dwie klasy MathTeacheri Footballersą pochodnymi Personklasy.

Podstawowy konstruktor Personklasy zadeklarował dwie właściwości: wiek i nazwę oraz ma blok inicjatora. Dostęp do bloku inicjującego (i funkcji składowych) klasy bazowej Personmożna uzyskać za pomocą obiektów klas pochodnych ( MathTeacheri Footballer).

Klasy pochodne MathTeacheri Footballermają własne funkcje członkowskie teachMaths()i playFootball()odpowiednio. Funkcje te są dostępne tylko z obiektów odpowiedniej klasy.

Kiedy MathTeachertworzony jest obiekt t1 klasy,

 val t1 = MathTeacher (25, "Jack")

Parametry są przekazywane do głównego konstruktora. W Kotlinie initblok jest wywoływany podczas tworzenia obiektu. Ponieważ MathTeacherjest pochodną Personklasy, szuka bloku inicjatora w klasie bazowej (Person) i wykonuje go. Gdyby MathTeachermiał blok init, kompilator wykonałby również blok init klasy pochodnej.

Następnie wywoływana jest teachMaths()funkcja obiektu t1using t1.teachMaths()instrukcji.

Program działa podobnie, gdy obiekt f1z Footballerklasy jest tworzony. Wykonuje blok init klasy bazowej. Następnie wywoływana jest playFootball()metoda Footballerklasy using instrukcja f1.playFootball().

Ważne uwagi: Dziedziczenie Kotlin

  • Jeśli klasa ma konstruktora podstawowego, podstawę należy zainicjować przy użyciu parametrów konstruktora podstawowego. W powyższym programie obie klasy pochodne mają dwa parametry agei name, a oba te parametry są inicjowane w konstruktorze podstawowym w klasie bazowej.
    Oto kolejny przykład:
     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") )  
    Tutaj główny konstruktor klasy pochodnej ma 3 parametry, a klasa bazowa ma 2 parametry. Zauważ, że oba parametry klasy bazowej są inicjowane.
  • W przypadku braku konstruktora podstawowego każda klasa bazowa musi zainicjować bazę (za pomocą słowa kluczowego super) lub przekazać ją innemu konstruktorowi, który to robi. Na przykład,
     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) ( ) )
    Aby dowiedzieć się więcej o tym, jak działa ten program, odwiedź Kotlin Secondary Constructor.

Zastępowanie funkcji i właściwości składowych

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

Możesz wywołać funkcje (i uzyskać dostęp do właściwości) klasy bazowej z klasy pochodnej za pomocą supersłowa kluczowego. Oto jak:

 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 uruchomieniu programu wynik będzie następujący:

 Mam 31 lat. Mój fałszywy wiek to 26 lat.

Interesujące artykuły...