Ereditarietà di Kotlin (con esempi)

In questo articolo imparerai l'ereditarietà. Più specificamente, cos'è l'ereditarietà e come implementarla in Kotlin (con l'aiuto di esempi).

L'ereditarietà è una delle caratteristiche chiave della programmazione orientata agli oggetti. Consente all'utente di creare una nuova classe (classe derivata) da una classe esistente (classe base).

La classe derivata eredita tutte le funzionalità dalla classe base e può avere funzionalità aggiuntive proprie.

Prima di entrare nei dettagli sull'eredità di Kotlin, ti consigliamo di controllare questi due articoli:

  • Classe e oggetti di Kotlin
  • Costruttore primario di Kotlin

Perché l'eredità?

Supponi, nella tua applicazione, di volere tre personaggi: un insegnante di matematica , un calciatore e un uomo d'affari .

Poiché tutti i personaggi sono persone, possono camminare e parlare. Tuttavia, hanno anche alcune abilità speciali. Un insegnante di matematica può insegnare matematica , un calciatore può giocare a calcio e un uomo d'affari può gestire un'impresa .

Puoi creare individualmente tre classi che possono camminare, parlare ed eseguire le loro abilità speciali.

In ciascuna delle classi, copieresti lo stesso codice per camminare e parlare per ogni personaggio.

Se vuoi aggiungere una nuova funzionalità: mangia, devi implementare lo stesso codice per ogni personaggio. Questo può facilmente diventare soggetto a errori (durante la copia) e duplicare i codici.

Sarebbe molto più semplice se avessimo una Personclasse con caratteristiche di base come parlare, camminare, mangiare, dormire e aggiungere abilità speciali a quelle caratteristiche come per i nostri personaggi. Questo viene fatto usando l'ereditarietà.

Utilizzando l'ereditarietà, ora non si implementa lo stesso codice per walk(), talk()e eat()per ogni classe. Hai solo bisogno di ereditarli .

Quindi, per MathTeacher(classe derivata), erediti tutte le funzionalità di una Person(classe base) e aggiungi una nuova funzionalità teachMath(). Allo stesso modo, per la Footballerclasse, erediti tutte le caratteristiche della Personclasse e aggiungi una nuova caratteristica playFootball()e così via.

Questo rende il tuo codice più pulito, comprensibile ed estendibile.

È importante ricordare: quando si lavora con l'ereditarietà, ogni classe derivata deve soddisfare la condizione se "è" una classe base o meno. Nell'esempio sopra, MathTeacher è a Person , Footballer è a Person . Non puoi avere qualcosa come, Businessman è un Business .

Eredità di Kotlin

Proviamo a implementare la discussione sopra nel codice:

 classe aperta Persona (età: Int) (// codice per mangiare, parlare, camminare) classe MathTeacher (età: Int): Persona (età) (// altre caratteristiche dell'insegnante di matematica) classe Calciatore (età: Int): Persona ( età) (// altre caratteristiche del calciatore) classe Uomo d'affari (età: Int): Persona (età) (// altre caratteristiche dell'uomo d'affari)

Qui, Personè una classe base, e le classi MathTeacher, Footballere Businessmansono derivate dalla classe Person.

Avviso, la parola chiave openprima della classe base, Person. È importante.

Per impostazione predefinita, le lezioni in Kotlin sono definitive. Se hai familiarità con Java, sai che una classe finale non può essere sottoclasse. Utilizzando l'annotazione aperta su una classe, il compilatore consente di derivarne nuove classi.

Esempio: ereditarietà di 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() )

Quando esegui il programma, l'output sarà:

Mi chiamo Jack. Ho 25 anni, insegno alle elementari. Il mio nome è Cristiano. La mia età è 29, gioco per LA Galaxy.

Qui, due classi MathTeachere Footballersono derivati ​​dalla Personclasse.

Il costruttore principale della Personclasse ha dichiarato due proprietà: età e nome e ha un blocco di inizializzazione. È possibile accedere al blocco di inizializzazione (e alle funzioni membro) della classe di base Persondagli oggetti delle classi derivate ( MathTeachere Footballer).

Classi derivate MathTeachere Footballerhanno le proprie funzioni membro teachMaths()e playFootball()rispettivamente. Queste funzioni sono accessibili solo dagli oggetti della rispettiva classe.

Quando MathTeacherviene creato l'oggetto t1 della classe,

 val t1 = MathTeacher (25, "Jack")

I parametri vengono passati al costruttore principale. In Kotlin, il initblocco viene chiamato quando viene creato l'oggetto. Poiché, MathTeacherè derivato dalla Personclasse, cerca il blocco inizializzatore nella classe base (Persona) e lo esegue. Se MathTeacheravesse il blocco init, il compilatore avrebbe eseguito anche il blocco init della classe derivata.

Successivamente, la teachMaths()funzione per oggetto t1viene chiamata utilizzando l' t1.teachMaths()istruzione.

Il programma funziona in modo simile quando viene creato l' oggetto f1della Footballerclasse. Esegue il blocco di inizializzazione della classe base. Quindi, il playFootball()metodo della Footballerclasse viene chiamato using statement f1.playFootball().

Note importanti: ereditarietà di Kotlin

  • Se la classe ha un costruttore primario, la base deve essere inizializzata utilizzando i parametri del costruttore primario. Nel programma precedente, entrambe le classi derivate hanno due parametri agee name, ed entrambi questi parametri sono inizializzati nel costruttore primario nella classe base.
    Ecco un altro esempio:
     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") )  
    Qui il costruttore principale della classe derivata ha 3 parametri e la classe base ha 2 parametri. Notare che vengono inizializzati entrambi i parametri della classe base.
  • In caso di nessun costruttore principale, ogni classe base deve inizializzare la base (usando la parola chiave super) o delegare a un altro costruttore che lo fa. Per esempio,
     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) ( ) )
    Per saperne di più su come funziona questo programma, visita il Kotlin Secondary Constructor.

Sostituzione delle funzioni e delle proprietà dei membri

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

È possibile chiamare le funzioni (e accedere alle proprietà) della classe base da una classe derivata utilizzando la superparola chiave. Ecco come:

 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) )

Quando esegui il programma, l'output sarà:

 La mia età è 31. La mia età falsa è 26.

Articoli interessanti...