Java est un langage orienté objet. Cela signifie que tout en Java est constitué de classes et de leurs objets, et obéit aux paradigmes de la POO (programmation orientée objet). L'un de ces paradigmes est l'héritage, un mécanisme en Java par lequel une classe est autorisée à hériter des fonctionnalités (champs et méthodes) d'une autre classe. En termes simples, en Java, l'héritage signifie créer de nouvelles classes basées sur celles existantes.
Acteurs clés de l’héritage en Java
- L'héritage est le concept selon lequel une classe peut répéter partiellement ou complètement les propriétés et les méthodes de son parent (la classe dont elle hérite).
- Une classe enfant, une sous-classe, une classe étendue ou une classe dérivée est une classe qui hérite d'une autre classe.
- Une classe parent, une superclasse ou une classe de base est une classe qui possède un certain nombre de fonctions, et ces fonctions peuvent être transmises (héritées) par une autre classe (classe enfant).
- Le remplacement de méthode consiste à modifier le comportement d’une méthode de classe dérivée. Il s’agit généralement d’un comportement plus spécifique et raffiné. Si vous remplacez une méthode dans l'héritier qui se trouve déjà dans la classe parent, elle remplace en quelque sorte la méthode parent.
- Une classe ne peut avoir qu’une seule classe ancêtre, mais chaque classe peut avoir plusieurs « enfants ».
Comment ça fonctionne
La chaîne d'héritage s'oriente de la classe la plus abstraite vers la classe la plus concrète. Autrement dit, la superclasse est la plus abstraite de la chaîne de classes. Il est souvent désigné comme abstrait (classe de base qui ne nécessite pas d'implémentation). Tous les autres cours sont plus spécifiques. Par exemple, il existe une classe appelée « Gadget ». Il peut avoir un « poids » sur le terrain, la capacité de la batterie, le niveau de charge sur le terrain et les méthodes (ou comportement) de « travail » et de charge. Dans ce cas, les méthodes peuvent être abstraites, c’est-à-dire qu’elles n’ont pas d’implémentation spécifique. Bien que nous ne puissions pas dire de quel type de gadget il s’agit, il s’agit absolument de n’importe quel gadget rechargeable. Créons une sous-classe Phone de la classe Gadget. Il n’a plus besoin de redéfinir le poids et la batterie, il les hérite simplement du gadget abstrait. Mais le comportement de l’ouvrage devra être clarifié. Vous pouvez également ajouter d'autres champs « diagonale d'écran », connecteurs, etc. Vous pouvez ajouter une nouvelle méthode « Mettre à jour le système d'exploitation ». Ensuite, nous pouvons créer deux classes supplémentaires et les deux seront héritées du téléphone, d'Android et de l'iPhone. Les deux classes héritent de tous les champs et méthodes du Gadget et du Smartphone, et les méthodes peuvent être remplacées. La première classe a besoin d'un champ « Nom de marque », alors que l'iPhone n'a pas besoin de ce champ, puisqu'une seule entreprise produit de tels smartphones.
class Gadget {
…
}
}
//subclass of Gadget class
class Phone extends Gadget {
…
}
//subclass of Phone class
class IPhone extends Phone {
…
}
//subclass of Phone class
class AndroidPhone extends Phone {
…
}
Une classe enfant hérite de tous les membres publics et protégés de la classe parent. Le package dans lequel se trouve la sous-classe n'a pas d'importance. Si la classe enfant se trouve dans le même package que la classe parent, elle hérite également des membres privés du package parent. Vous pouvez utiliser les membres hérités tels quels, les remplacer, les masquer ou ajouter de nouveaux membres :
- Vous pouvez utiliser les champs hérités directement, comme n'importe quel autre champ.
- Vous pouvez déclarer un champ dans la classe enfant qui porte le même nom que dans la classe parent. C'est le cacher (donc mieux vaut ne pas le faire).
- Vous pouvez déclarer de nouveaux champs dans la classe enfant (ceux que la classe parent n'a pas).
- Les méthodes héritées peuvent être utilisées directement sans substitution dans la classe dérivée.
- Vous pouvez également écrire une nouvelle méthode d'instance dans une sous-classe qui a la même signature qu'une méthode de la classe parent. Cette procédure le remplace.
- Vous pouvez déclarer de nouvelles méthodes dans la classe enfant qui n'ont pas été déclarées dans la classe Parent.
- Vous pouvez écrire un constructeur de sous-classe qui appelle le constructeur de superclasse implicitement ou avec le mot-clé super.
Exemple
Créons une classe de base MusicalInstrument avec des champs de poids et de marque, ainsi qu'une méthode work() . Nous définissons également un constructeur.
public class MusicalInstrument {
int weight;
String tradeMark;
public MusicalInstrument(int weight, String tradeMark) {
this.weight = weight;
this.tradeMark = tradeMark;
}
public void work() {
System.out.println("the instrument is playing...");
}
}
On ne sait absolument pas de quel type d’instrument de musique il s’agit et comment en jouer. Créons un instrument plus spécifique, le violon. Il aura les mêmes champs que dans l'Instrument de Musique (ils seront appelés dans le constructeur à l'aide du mot-clé super. On peut aussi surcharger la méthode de travail et créer une méthode de réglage corde par corde du violon.
public class Violin extends MusicalInstrument {
String master;
String owner;
int age;
boolean isTuned;
public Violin(int weight, String tradeMark, String master, String owner, int age, boolean isTuned) {
super(weight, tradeMark);
this.master = master;
this.owner = owner;
this.age = age;
this.isTuned = isTuned;
}
@Override
public void work() {
System.out.println("THe violin's playing");
}
public void violinTuning () {
System.out.println("I'm tuning 1st string...");
System.out.println("I'm tuning 2nd string...");
System.out.println("I'm tuning 3rd string...");
System.out.println("I'm tuning 4th string...");
}
}
Créons une classe Demo pour tester la classe Violin et voir exactement comment fonctionne l'héritage.
public class InheritDemo {
public static void main(String[] args) {
Violin violin = new Violin(1, null, "Amati", "Kremer", 285, false);
violin.violinTuning();
violin.work();
}
}
Dans ce cas, le résultat du programme sera le suivant :
J'accorde la 1ère corde... J'accorde la 2ème corde... J'accorde la 3ème corde... J'accorde la 4ème corde... Le violon joue
Autrement dit, s’il existe une méthode substituée dans la classe enfant, la méthode ancêtre ne sera plus appelée. Et s'il n'y était pas ? Autrement dit, la classe Violon ressemble à ceci :
public class Violin extends MusicalInstrument {
String master;
String owner;
int age;
boolean isTuned;
public Violin(int weight, String tradeMark, String master, String owner, int age, boolean isTuned) {
super(weight, tradeMark);
this.master = master;
this.owner = owner;
this.age = age;
this.isTuned = isTuned;
}
// @Override
// }
public void violinTuning () {
System.out.println("I'm tuning 1st string...");
System.out.println("I'm tuning 2nd string...");
System.out.println("I'm tuning 3rd string...");
System.out.println("I'm tuning 4th string...");
}
}
Le résultat est :
J'accorde la 1ère corde... J'accorde la 2ème corde... J'accorde la 3ème corde... J'accorde la 4ème corde... l'instrument joue...
Autrement dit, la méthode ancêtre sera automatiquement appelée. À propos, la classe enfant peut être définie via l'ancêtre, c'est-à-dire pour effectuer une conversion ascendante :
Parent parent = new Child()
Cette initialisation permet d'accéder uniquement aux membres présents dans la classe parent et aux méthodes remplacées. Dans notre exemple, ce serait :
public class InheritDemo {
public static void main(String[] args) {
MusicalInstrument violin = new Violin(1, null, "Amati", "Kremer", 285, false);
//violin.violinTuning();
violin.work();
}
}
Dans un tel cas, nous ne sommes pas en mesure de configurer la méthode violon. Cependant en même temps, la méthode work() de la classe descendante sera appelée, si elle existe.
La hiérarchie des classes de la plateforme Java
En Java, tout est constitué de classes et elles sont subordonnées à une hiérarchie. La question se pose : existe-t-il une classe dont toutes les autres sont héritées ? La réponse est oui, une telle classe existe effectivement. Et cela s'appelle simplement Object . La classe Object du package java.lang définit et implémente un comportement commun à toutes les classes, y compris celles que vous créez. Sur la plateforme Java, de nombreuses classes dérivent directement de Object , d'autres classes dérivent de certaines de ces classes, et ainsi de suite, formant une hiérarchie de classes.Types d'héritage en Java
Soulignons quelques types d'héritage en Java. 1. Héritage unique Ce type est comme dans notre exemple ci-dessus, les sous-classes héritent des fonctionnalités d'une super classe. Dans l'image ci-dessous, la classe A sert de classe de base pour la classe dérivée B. 2. Héritage multiniveau Il s'agit simplement d'une chaîne d'héritage, c'est-à-dire qu'il existe une classe de base A, la classe B en est héritée et la classe C est hérité de la classe B. En Java, une classe ne peut pas accéder directement aux membres des grands-parents. 3. Héritage hiérarchique Dans l'héritage hiérarchique, une classe sert de super-classe (classe de base) pour plusieurs sous-classes. Ci-dessus, nous avons donné un exemple de la classe Phone, qui peut avoir deux « enfants » : AndroidPhone et IPhone.
class A {
public void printA() {
System.out.println("A");
}
}
class B extends A {
public void printB() {
System.out.println(" B"); }
}
class C extends A {
public void printC() {
System.out.println("C");
}
}
class D extends A {
public void printD() {
System.out.println("D");
}
}
public class Demo {
public static void main(String[] args)
{
B objB = new B();
objB.printA();
objB.printB();
C objC = new C();
objC.printA();
objC.printC();
D objD = new D();
objD.printA();
objD.printD();
}
}
Le résultat est :
A B A C A D
4. L'héritage multiple, c'est-à-dire la présence de plusieurs ancêtres... mais attendez, l'héritage multiple classique n'est pas supporté en Java. Dans une certaine mesure, il peut être implémenté en utilisant non pas des classes, mais des interfaces.
interface A {
public void printA();
}
interface B {
public void printB();
}
interface C extends A, B {
public void print();
}
class InheritDemo implements C {
@Override
public void print()
{
System.out.println("Print something");
}
@Override
public void printA() {
}
@Override
public void printB() {
}
}
GO TO FULL VERSION