Héritage Java


Concept de l'héritage

L'héritage est une pierre angulaire de la technologie de programmation orientée objet Java, car il permet de créer des classes hiérarchiques.

L'héritage signifie qu'une sous-classe hérite des caractéristiques et des comportements d'une classe parente, de sorte que les objets (instances) de la sous-classe possèdent les champs et méthodes d'instance de la classe parente, ou que la sous-classe hérite des méthodes de la classe parente, donnant à la sous-classe les mêmes comportements que la classe parente.

L'héritage dans la vie quotidienne :

Les lapins et les moutons appartiennent à la classe des herbivores, tandis que les lions et les léopards appartiennent à la classe des carnivores.

Les herbivores et les carnivores appartiennent également à la classe des animaux.

Par conséquent, la relation que l’héritage doit satisfaire est : is-a. La classe parente est plus générale, et la sous-classe est plus spécifique.

Bien que les herbivores et les carnivores appartiennent tous deux aux animaux, il existe des différences dans leurs attributs et leurs comportements. Par conséquent, une sous-classe aura les caractéristiques générales de la classe parente ainsi que ses propres caractéristiques.

Format d’héritage de classe

En Java, vous pouvez utiliser le mot-clé extends pour déclarer qu’une classe hérite d’une autre classe. La forme générale est la suivante :

Format d’héritage de classe

classClasse parente{ } classSous-classeextendsClasse parente{ }

Pourquoi avons-nous besoin de l’héritage ?

Ensuite, illustrons ce besoin avec un exemple.

Développez une classe d’animaux, où les animaux sont un pingouin et une souris, avec les exigences suivantes :

  • Pingouin : attributs (name, id), méthodes (eat, sleep, self-introduction)
  • Souris : attributs (name, id), méthodes (eat, sleep, self-introduction)

Classe Penguin :

public class Penguin { private String name; private int id; public Penguin(String myName, int myid) { name = myName; id = myid; } public void eat(){ System.out.println(name+"Mange"); } public void sleep(){ System.out.println(name+"Dort"); } public void introduction() { System.out.println("Bonjour tout le monde ! Je suis" + id + "Number" + name + "."); } }

Classe Mouse :

public class Mouse { private String name; private int id; public Mouse(String myName, int myid) { name = myName; id = myid; } public void eat(){ System.out.println(name+"Mange"); } public void sleep(){ System.out.println(name+"Dort"); } public void introduction() { System.out.println("Bonjour tout le monde ! Je suis" + id + "Number" + name + "."); } }

À partir de ces deux extraits de code, nous pouvons voir que le code est dupliqué, ce qui rend le code volumineux et gonflé, et la maintenabilité est faible (principalement parce que lorsque des modifications sont nécessaires plus tard, de nombreuses parties du code doivent être modifiées, ce qui est source d'erreurs). Pour résoudre fondamentalement le problème de ces deux extraits de code, l'héritage est nécessaire. Extrayez les parties communes des deux extraits de code pour former une classe parente :

Classe parente commune :

public class Animal { private String name; private int id; public Animal(String myName, int myid) { name = myName; id = myid; } public void eat(){ System.out.println(name+"Mange"); } public void sleep(){ System.out.println(name+"Dort"); } public void introduction() { System.out.println("Bonjour tout le monde ! Je suis" + id + "Number" + name + "."); } }

Cette classe Animal peut servir de classe parente. Après que les classes Penguin et Mouse héritent de cette classe, elles auront les attributs et les méthodes de la classe parente. Les sous-classes n'auront plus de code dupliqué, la maintenabilité est améliorée, le code est plus concis et la réutilisabilité du code est améliorée (la réutilisabilité signifie principalement qu'il peut être utilisé plusieurs fois sans réécrire le même code). Code après héritage :

Classe Penguin :

public class Penguin extends Animal { public Penguin(String myName, int myid) { super(myName, myid); } }

Classe Mouse :

public class Mouse extends Animal { public Mouse(String myName, int myid) { super(myName, myid); } }

Types d'héritage

Notez que Java ne prend pas en charge l'héritage multiple, mais il prend en charge l'héritage à plusieurs niveaux.


Caractéristiques de l'héritage

  • Une sous-classe possède tous les attributs et méthodes non privés de la classe parente.

  • Une sous-classe peut avoir ses propres attributs et méthodes, ce qui signifie qu'une sous-classe peut étendre la classe parente.

  • Une sous-classe peut implémenter les méthodes de la classe parente à sa manière.

  • L'héritage Java est un héritage simple, mais l'héritage à plusieurs niveaux est possible. L'héritage simple signifie qu'une sous-classe ne peut hériter que d'une seule classe parente. L'héritage à plusieurs niveaux signifie, par exemple, que la classe B hérite de la classe A, et que la classe C hérite de la classe B. Ainsi, en termes de relations, la classe B est la classe parente de la classe C, et la classe A est la classe parente de la classe B. C'est une caractéristique qui distingue l'héritage Java de l'héritage C++.

  • Cela augmente le couplage entre les classes (un inconvénient de l'héritage ; un couplage élevé rend les liens entre le code plus étroits et l'indépendance du code plus faible).


Mots-clés de l'héritage

L'héritage peut être implémenté à l'aide des deux mots-clés extends et implements. De plus, toutes les classes héritent de java.lang.Object. Lorsqu'une classe n'utilise pas ces deux mots-clés d'héritage, elle hérite d'Object par défaut (cette classe se trouve dans lejava.langpackage, donc il n'est pas nécessaire d'import) la classe ancêtre.

mot-clé extends

En Java, l’héritage de classe est un héritage simple ; c’est-à-dire qu’une sous-classe ne peut avoir qu’une seule classe parente, donc extends ne peut hériter que d’une seule classe.

mot-clé extends

public class Animal { private String name; private int id; public Animal(String myName, int myid) { //Initialiser les valeurs des propriétés } public void eat() { //Implémentation spécifique de la méthode eat } public void sleep() { //Implémentation spécifique de la méthode sleep } } public class Penguin extends Animal{ }

mot-clé implements

L’utilisation du mot-clé implements peut indirectement donner à Java les caractéristiques de l’héritage multiple. Il est utilisé lorsqu’une classe hérite d’interfaces, et elle peut hériter de plusieurs interfaces en même temps (les interfaces sont séparées par des virgules).

mot-clé implements

public interface A { public void eat(); public void sleep(); } public interface B { public void show(); } public class C implements A,B { }

mots-clés super et this

mot-clé super :Nous pouvons utiliser le mot-clé super pour accéder aux membres de la classe parente ; il est utilisé pour référencer la classe parente de l'objet courant.

mot-clé this :Une référence à lui-même, désignant l'objet courant, c'est-à-dire l'instance d'objet à laquelle appartient la méthode ou le constructeur en cours.

Exemple

class Animal { void eat() { System.out.println("animal : eat"); } } class Dog extends Animal { void eat() { System.out.println("dog : eat"); } void eatTest() { this.eat(); //this appelle sa propre méthode super.eat(); //super appelle la méthode de la classe parente } } public class Test { public static void main(String[] args) { Animal a = new Animal(); a.eat(); Dog d = new Dog(); d.eatTest(); } }

Le résultat de sortie est:

animal : eat
dog : eat
animal : eat

mot-clé final

final peut être utilisé pour modifier des variables (y compris les attributs de classe, les attributs d'objet, les variables locales et les paramètres formels), des méthodes (y compris les méthodes de classe et les méthodes d'objet) et des classes.

final signifie « final ».

Utiliser le mot-clé final pour déclarer une classe définit la classe comme une classe finale qui ne peut pas être héritée ; ou il est utilisé pour modifier des méthodes, et ces méthodes ne peuvent pas être redéfinies par les sous-classes :

  • Déclarer une classe :

    final class 类名 {//类体}
  • Déclarer une méthode :

    修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}

Remarque :Dans une classe définie avec final, ses attributs et méthodes ne sont pas final.


Constructeur

Une sous-classe n'hérite pas du constructeur de la classe parente (méthode de construction ou fonction constructeur) ; elle ne fait que l'appeler (implicitement ou explicitement). Si le constructeur de la classe parente a des paramètres, alors dans le constructeur de la sous-classe vous devez explicitement utiliser lesupermot-clé pour appeler le constructeur de la classe parente avec une liste de paramètres appropriée.

Si le constructeur de la classe parente n'a pas de paramètres, alors dans le constructeur de la sous-classe il n'est pas nécessaire d'utiliser lesupermot-clé pour appeler le constructeur de la classe parente ; le système appellera automatiquement le constructeur sans argument de la classe parente.

Exemple

class SuperClass { private int n; //Constructeur sans argument public SuperClass() { System.out.println("SuperClass()"); } //Constructeur avec paramètres public SuperClass(int n) { System.out.println("SuperClass(int n)"); this.n = n; } } //SubClass héritage de classe class SubClass extends SuperClass { private int n; //Constructeur sans argument : appelle automatiquement le constructeur sans argument de la classe parente public SubClass() { System.out.println("SubClass()"); } //Constructeur avec paramètres : appelle le constructeur de la classe parente qui a des paramètres public SubClass(int n) { super(300); System.out.println("SubClass(int n): " + n); this.n = n; } } //SubClass2 héritage de classe class SubClass2 extends SuperClass { private int n; //Constructeur sans argument : appelle le constructeur de la classe parente qui a des paramètres public SubClass2() { super(300); System.out.println("SubClass2()"); } //Constructeur avec paramètres : appelle automatiquement le constructeur sans argument de la classe parente public SubClass2(int n) { System.out.println("SubClass2(int n): " + n); this.n = n; } } public class TestSuperSub { public static void main(String[] args) { System.out.println("------Héritage de la classe SubClass------"); SubClass sc1 = new SubClass(); SubClass sc2 = new SubClass(100); System.out.println("------Héritage de la classe SubClass2------"); SubClass2 sc3 = new SubClass2(); SubClass2 sc4 = new SubClass2(200); } }

Le résultat de sortie est:

------SubClass 类继承------
SuperClass()
SubClass()
SuperClass(int n)
SubClass(int n): 100
------SubClass2 类继承------
SuperClass(int n)
SubClass2()
SuperClass()
SubClass2(int n): 200
Autres extensions