Je ne savais pas grand-chose de l'héritage Java. Je pensais que je le savais d'une manière ou d'une autre, mais je ne l'ai pas compris d'une manière ou d'une autre, oui. : innocent:
Dans cet article, je voudrais vous présenter l'héritage Java que j'ai personnellement expérimenté, "je savais" mais "je ne savais pas". J'espère que cela vous aidera à comprendre l'héritage Java.
※ Mise en garde
coming soon
L'héritage est ** "créer (définir) une nouvelle classe basée sur une classe existante" **. Cette fois, -Classe d'héritage: ** Super classe ** ou ** Classe de base ** -Classe héritée: ** Sous-classe ** ou ** Classe dérivée ** (Dans cet article, nous utilisons l'expression superclasse / sous-classe).
Dans l'exemple ci-dessous, nous créons une classe Cat à partir d'une classe Mammals.
//Super classe
class Mammals { }
//Sous-classe
class Cat extends Mammals { }
C'est tout pour l'héritage. C'est facile!
... Je le sais! Cependant, je ne sais pas ce qu'il adviendra de l'héritage (surtout moi).
Du chapitre suivant, quatre perspectives auxquelles je prête personnellement attention
Par exemple, une déclaration comme ↓ entraînera une erreur de compilation.
//Super classe partie 1
class Mammals { }
//Super classe partie 2
class Reptiles { }
//Sous-classe
class Cat extends Mammals, Reptiles { }
Voir le code ci-dessous. La classe abstraite Mammals a des méthodes abstraites eact, walk et des méthodes concrètes sleep. La classe Cat, qui hérite de Mammals, remplace les méthodes de marche et de sommeil.
Mammals.java
public abstract class Mammals {
public abstract void eat();
public abstract void walk();
public void sleep() {}
}
Cat.java
public class Cat extends Mammals {
public void walk() {}
public void sleep() {}
}
Bon, le code dans ↑, mais quand je le compile, j'obtiens une erreur (si vous le regardez avec un éditeur comme Eclipse, VSCode, il ne fait aucun doute qu'il est rouge vif).
La raison, comme vous pouvez vous y attendre, est que ** les méthodes abstraites de la classe abstraite ne sont pas remplacées dans la classe concrète **. Cette fois, j'obtiens une erreur de compilation car je n'ai pas surchargé eat () de Mammals dans Cat. Remplacez toutes les méthodes abstraites [^ 20].
Le code ci-dessous hérite de la classe Mammals pour créer les classes Cat et Dog.
class Mammals { } //Classe de mammifères
class Cat extends Mammals { } //Classe de chat
class Dog extends Mammals { } //Classe de chien
public class Main {
public static void main(String[] args) {
Cat catA = new Cat();
Dog dogA = new Dog();
//Caster une instance de type Chat en type Mammifères
Mammals mammals = (Mammals) catA; // OK
//Caster une instance de type Chat en type Chien
Dog dogB = (Dog) catA; //Erreur de compilation NG
}
}
Java vérifie également ** s'il peut être converti au moment de la compilation (= cast en une classe qui a une relation d'héritage) **. C'est donc une erreur de compilation, pas une erreur d'exécution!
Le code qui ne peut pas être converti en général, pas seulement l'héritage, entraînera une erreur de compilation.
Le code suivant entraînera une erreur de compilation. Lors de l'héritage de la classe Mammals et de la substitution de la méthode eat dans la classe Cat, la plage de divulgation est plus stricte que la méthode eat d'origine.
class Mammals {
void eat() {}
}
class Cat extends Mammals {
private void eat() {}
}
Voici les accesseurs de méthode couramment utilisés (modificateurs d'accès).
//Strict ← Gamme de divulgation → Loose
private protected /*(Aucun accesseur)*/ public
Accesseur | La description |
---|---|
private | Uniquement disponible dans la même classe |
protected | Disponible à partir des classes du même package ou des classes qui héritent de la classe cible |
(Aucun accesseur) | Uniquement disponible à partir des classes du même package |
public | Disponible dans toutes les classes |
Même si vous en héritez, vous ne pouvez pas en hériter ** Champs et méthodes privés (y compris les constructeurs) ** est!
En haut, j'ai dit: "Même si vous héritez, le constructeur ne peut pas être hérité", mais il y a quelque chose dont il faut être conscient. Autrement dit, ** le constructeur de la superclasse est exécuté ** avant que le constructeur de la sous-classe ne soit exécuté.
Voir le code ci-dessous. Il existe des classes A, B, C, où C hérite de B et B hérite de A. Et dans chaque constructeur, le nom de la classe est sorti sur la console (le code est cité de la référence 2 dans différents formats).
A.java
class A {
public A() {
System.out.print("A");
}
}
class B extends A {
public B() {
System.out.print("B");
}
}
class C extends B {
public C() {
System.out.print("C");
}
}
public class Main {
public static void main(String[] args) {
new C(); // ABC
}
}
Et avez-vous vu ce qui se passe lorsque vous exécutez ce main () ... Oui, ** les constructeurs A, B, C fonctionnent tous! !! ** **
... Je suis désolé, j'ai exagéré [^ 30].
Toute l'explication est pourquoi cela se produit, mais je voudrais citer la référence 3 p.429.
ʻEn fait, en Java, la règle est que "tous les constructeurs doivent appeler le constructeur de la partie d'instance interne (= classe parente) au début." «[^ 35]
En d'autres termes, compte tenu de la véritable apparence et de l'ordre d'exécution du code précédent,
A.java
class A {
public A() {
System.out.print("A"); // 3
}
}
class B extends A {
public B() {
super(); //Appelez le constructeur de A 2
System.out.print("B"); // 4
}
}
class C extends B {
public C() {
super(); //Appelez le constructeur 1 de B
System.out.print("C"); // 5
}
}
public class Main {
public static void main(String[] args) {
new C(); //Instancier C 0
}
}
Si B () est exécuté lorsque C () est appelé, A () est appelé à l'intérieur de B (), et ainsi de suite, la classe héritière hérite d'une autre classe. Tente d'exécuter d'abord le constructeur de la classe héritée.
De plus, à l'intérieur de la sous-classe, si vous n'avez pas appelé le constructeur de la classe superclasse, le compilateur ajoutera automatiquement super ()
[^ 37] [^ 40]!
cependant,
-Appeler explicitement le constructeur de la super classe (super ()
ou super (str)
)
-Appeler le constructeur surchargé (this ()
ou this (str)
)
Si vous faites l'un ou l'autre, le compilateur n'ajoutera pas super ()
tout seul.
Les constructeurs de sous-classes appellent les constructeurs de superclasses ... Même si vous savez cela, si vous appelez le constructeur d'une classe héritée plusieurs fois de cette manière, vous serez déçu.
En relation avec "02. Faites attention à l'ordre d'exécution des constructeurs", un tel déclencheur apparaît également. C'est, ** Le code qui double-appelle le constructeur de la superclasse entraînera une erreur de compilation ** à propos de ça.
Tout d'abord, jetez un œil au code suivant! (Reporté de la référence 2 p.362-363 avec quelques changements de format)
Classe de mammifères
public class Mammals {
String name;
int age;
public Mammals(String name, int age) {
this.name = name;
this.age = age;
}
}
Classe de chat
class Cat extends Mammals {
String color
publip Cat(String color) {
this.color = color;
}
public Cat(String name, int num, String color) {
super(name, num);
this(color);
}
}
Classe principale
public class Main {
public static void main(String[] args) {
Cat cat1 = new Cat("white");
Cat cat2 = new Cat("mike", 2, "Black");
System.out.println(cat1.name + ", " + "" + "")
}
}
Maintenant, que pensez-vous de ce code, le compilateur?
La bonne réponse est une erreur de compilation sur les lignes 3 et 8 de la cat class
!
Pour voir pourquoi, nous supposerons que ce code a été exécuté et suivrons le processus pour chaque instance générée!
① Processus pour générer l'instance cat1
Puisqu'il y a un argument comme Cat cat1 = new Cat (" white ");
, publip Cat (String color)
est exécuté.
Avant ..., Cat hérite de Mammals, donc le constructeur de Mammals est exécuté.
String color
publip Cat(String color) {
super(); //Ajouté automatiquement au moment de la compilation
this.color = color;
}
Cependant, la classe Mammals n'a pas de constructeur sans argument public Mammals ();
!
Si vous essayez d'exécuter une méthode qui n'existe pas, vous obtiendrez une erreur sur la ligne qui dit publip Cat (String color)
[^ 45].
② Processus pour générer l'instance cat2
Cette fois, nous créons une instance avec 3 arguments.
Par conséquent, le constructeur correspondant ci-dessous est exécuté!
public Cat(String name, int num, String color) {
super(name, num);
this(color);
}
Tout d'abord, le constructeur de la super classe «publip Cat (String color)» est exécuté. Ce n'est pas un problème tel qu'il existe.
Mais le code de la ligne suivante, exécutant cette fois le constructeur de classe Cat publip Cat (String color)
.
Je pense que ce sera la même erreur que dans ①, mais je me retrouve pris dans un autre type d'erreur de compilation.
La raison en est que vous allez ** appeler le constructeur de la superclasse deux fois **.
En Java, il n'est pas possible d'appeler le constructeur surchargé après avoir appelé le constructeur `superclass. «[^ 50]
Cette fois, «publip Cat (String color)» est le constructeur surchargé. Cela a été fait après super ();
, entraînant une erreur.
Dans le test réel, à l'intérieur du constructeur,
super();
this();
Quand je regarde le code, j'obtiens une erreur de compilation à la partie this ();
! Il semble bon de se souvenir!
Merci d'avoir lu jusqu'au bout.
[ref]: Liste des références [^ 5]: Habituellement, l'éditeur ou le compilateur vous le dira, donc peu importe si vous ne le comprenez pas, mais si vous devez le remarquer vous-même, vous ne pouvez pas le dire! Ça veut dire. [^ 20]: En passant, les méthodes abstraites ne peuvent être définies que dans des classes abstraites. Si vous n'implémentez pas la méthode dans la classe Cat, c'est une bonne idée d'attacher également la classe Cat. [^ 30]: Je l'ai écrit de manière exagérée. [^ 35]: Référence 3 à partir de la p.429 [^ 37]: Ce n'est pas comme si le code apparaissait tout seul. Le code est uniquement compilé dans le corps écrit en super (). [^ 40]: En premier lieu, c'est une interprétation pour savoir si vous devez exécuter le constructeur de la super classe, mais si le constructeur est une méthode pour générer cette classe, ce sera la base avant de créer la sous-classe. Est-ce un endroit où vous devez vous préparer à partir de la classe dans laquelle vous êtes (= super classe)? [^ 45]: Le compilateur Java vérifie également si la méthode que vous essayez d'exécuter existe, elle est donc traitée comme une erreur de compilation! [^ 50]: Référence 2 à partir de la p.416
Recommended Posts