Dans cet article, vous découvrirez l'héritage. Plus précisément, qu'est-ce que l'héritage et comment l'implémenter dans Kotlin (à l'aide d'exemples).
L'héritage est l'une des principales caractéristiques de la programmation orientée objet. Il permet à l'utilisateur de créer une nouvelle classe (classe dérivée) à partir d'une classe existante (classe de base).
La classe dérivée hérite de toutes les fonctionnalités de la classe de base et peut avoir ses propres fonctionnalités supplémentaires.
Avant d'entrer dans les détails sur l'héritage de Kotlin, nous vous recommandons de consulter ces deux articles:
- Classe et objets Kotlin
- Constructeur principal Kotlin
Pourquoi l'héritage?
Supposons que, dans votre application, vous vouliez trois personnages: un professeur de mathématiques , un footballeur et un homme d'affaires .
Puisque tous les personnages sont des personnes, ils peuvent marcher et parler. Cependant, ils ont également des compétences spéciales. Un professeur de mathématiques peut enseigner les mathématiques , un footballeur peut jouer au football et un homme d'affaires peut diriger une entreprise .
Vous pouvez créer individuellement trois classes qui peuvent marcher, parler et exécuter leurs compétences spéciales.
Dans chacune des classes, vous copieriez le même code pour marcher et parler pour chaque personnage.
Si vous souhaitez ajouter une nouvelle fonctionnalité - eat, vous devez implémenter le même code pour chaque caractère. Cela peut facilement devenir sujet à des erreurs (lors de la copie) et des codes en double.
Ce serait beaucoup plus facile si nous avions une Person
classe avec des fonctionnalités de base comme parler, marcher, manger, dormir et ajouter des compétences spéciales à ces fonctionnalités selon nos personnages. Cela se fait en utilisant l'héritage.
Utilisation de l' héritage, maintenant , vous ne met pas en œuvre le même code pour walk()
, talk()
et eat()
pour chaque classe. Vous avez juste besoin d'en hériter .
Ainsi, pour MathTeacher
(classe dérivée), vous héritez de toutes les fonctionnalités d'une Person
(classe de base) et ajoutez une nouvelle fonctionnalité teachMath()
. De même, pour la Footballer
classe, vous héritez de toutes les fonctionnalités de la Person
classe et ajoutez une nouvelle fonctionnalité playFootball()
et ainsi de suite.
Cela rend votre code plus propre, compréhensible et extensible.
Il est important de se rappeler: Lorsque vous travaillez avec l'héritage, chaque classe dérivée doit satisfaire à la condition qu'elle "soit" une classe de base ou non. Dans l'exemple ci-dessus, MathTeacher
est a Person
, Footballer
est a Person
. Vous ne pouvez pas avoir quelque chose comme, Businessman
est un Business
.
Héritage de Kotlin
Essayons d'implémenter la discussion ci-dessus dans le code:
classe ouverte Person (age: Int) (// code pour manger, parler, marcher) class MathTeacher (age: Int): Person (age) (// autres caractéristiques du professeur de mathématiques) class Footballer (age: Int): Person ( age) (// autres caractéristiques du footballeur) classe Homme d'affaires (age: Int): Personne (âge) (// autres caractéristiques de l'homme d'affaires)
Ici, Person
est une classe de base, et les classes MathTeacher
, Footballer
et Businessman
sont dérivées de la classe Person.
Remarquez, le mot - clé open
avant la classe de base, Person
. C'est important.
Par défaut, les classes de Kotlin sont finales. Si vous êtes familiarisé avec Java, vous savez qu'une classe finale ne peut pas être sous-classée. En utilisant l'annotation ouverte sur une classe, le compilateur vous permet d'en dériver de nouvelles classes.
Exemple: héritage de 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() )
Lorsque vous exécutez le programme, la sortie sera:
Mon nom est Jack. J'ai 25 ans et j'enseigne à l'école primaire. Mon nom est Cristiano. J'ai 29 ans, je joue pour LA Galaxy.
Ici, deux classes MathTeacher
et Footballer
sont dérivées de la Person
classe.
Le constructeur principal de la Person
classe a déclaré deux propriétés: l'âge et le nom, et il a un bloc d'initialisation. Le bloc initiateur (et les fonctions membres) de la classe de base Person
sont accessibles par les objets des classes dérivées ( MathTeacher
et Footballer
).
Les classes dérivées MathTeacher
et Footballer
ont leurs propres fonctions membres teachMaths()
et playFootball()
respectivement. Ces fonctions ne sont accessibles qu'à partir des objets de leur classe respective.
Lorsque l'objet t1 de MathTeacher
classe est créé,
val t1 = MathTeacher (25, "Jack")
Les paramètres sont transmis au constructeur principal. Dans Kotlin, le init
bloc est appelé lorsque l'objet est créé. Puisque, MathTeacher
est dérivé de la Person
classe, il recherche le bloc d'initialisation dans la classe de base (Person) et l'exécute. Si le MathTeacher
bloc avait init, le compilateur aurait également exécuté le bloc init de la classe dérivée.
Ensuite, la teachMaths()
fonction d'objet t1
est appelée using t1.teachMaths()
statement.
Le programme fonctionne de manière similaire lorsque l'objet f1
de la Footballer
classe est créé. Il exécute le bloc init de la classe de base. Ensuite, la playFootball()
méthode de Footballer
classe est appelée using statement f1.playFootball()
.
Notes importantes: héritage de Kotlin
- Si la classe a un constructeur principal, la base doit être initialisée à l'aide des paramètres du constructeur principal. Dans le programme ci-dessus, les deux classes dérivées ont deux paramètres
age
etname
, et ces deux paramètres sont initialisés dans le constructeur principal de la classe de base.
Voici un autre exemple: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") )
- En cas d'absence de constructeur principal, chaque classe de base doit initialiser la base (en utilisant le mot clé super), ou déléguer à un autre constructeur qui fait cela. Par exemple,
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) ( ) )
Remplacement des fonctions et propriétés des membres
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
Vous pouvez appeler des fonctions (et accéder aux propriétés) de la classe de base à partir d'une classe dérivée à l'aide de super
mot-clé. Voici comment:
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) )
Lorsque vous exécutez le programme, la sortie sera:
Mon âge est de 31 ans. Mon faux âge est de 26 ans.