Ich wusste nicht viel über Java-Vererbung. Ich dachte, ich wüsste es irgendwie, aber ich habe es irgendwie nicht verstanden, ja. : unschuldig:
In diesem Artikel möchte ich die Java-Vererbung vorstellen, die ich persönlich erlebt habe: "Ich wusste", aber "Ich habe nicht". Ich hoffe, es hilft Ihnen, die Java-Vererbung zu verstehen.
※ Hinweis
coming soon
Vererbung ist ** "Erstellen (Definieren) einer neuen Klasse basierend auf einer vorhandenen Klasse" **. In diesem Moment, Vererbungsklasse: ** Superklasse ** oder ** Basisklasse ** -Ererbte Klasse: ** Unterklasse ** oder ** Abgeleitete Klasse ** (In diesem Artikel verwenden wir den Ausdruck Superklasse / Unterklasse).
Im folgenden Beispiel erstellen wir eine Cat-Klasse aus einer Mammals-Klasse.
//Super Klasse
class Mammals { }
//Unterklasse
class Cat extends Mammals { }
Das ist alles für die Vererbung. Es ist einfach!
... Ich weiß das! Ich weiß jedoch nicht, was mit der Vererbung passieren wird (besonders ich).
Ab dem nächsten Kapitel vier Perspektiven, auf die ich persönlich achte
Beispielsweise führt eine Deklaration wie ↓ zu einem Kompilierungsfehler.
//Superklasse Teil 1
class Mammals { }
//Superklasse Teil 2
class Reptiles { }
//Unterklasse
class Cat extends Mammals, Reptiles { }
Siehe den Code unten. Die abstrakte Klasse Mammals verfügt über abstrakte Methoden zum Essen, Gehen und konkreten Schlafmethoden. Die Cat-Klasse, die Säugetiere erbt, überschreibt die Geh- und Schlafmethoden.
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() {}
}
Nun, der Code in ↑, aber wenn ich ihn kompiliere, erhalte ich eine Fehlermeldung (wenn Sie ihn mit einem Editor wie Eclipse, VSCode betrachten, besteht kein Zweifel daran, dass er hellrot ist).
Der Grund ist, wie zu erwarten, dass ** die abstrakten Methoden der abstrakten Klasse in der konkreten Klasse nicht überschrieben werden **. Dieses Mal erhalte ich einen Kompilierungsfehler, weil ich Mammals 'eat () in Cat nicht überladen habe. Überschreiben Sie alle abstrakten Methoden [^ 20].
Der folgende Code erbt von der Mammals-Klasse, um die Cat- und Dog-Klassen zu erstellen.
class Mammals { } //Säugetierklasse
class Cat extends Mammals { } //Katzenklasse
class Dog extends Mammals { } //Hundeklasse
public class Main {
public static void main(String[] args) {
Cat catA = new Cat();
Dog dogA = new Dog();
//Wirf eine Instanz vom Typ Katze in den Typ Säugetiere
Mammals mammals = (Mammals) catA; // OK
//Wirf eine Instanz vom Typ Katze in den Typ Hund
Dog dogB = (Dog) catA; //NG-Kompilierungsfehler
}
}
Java ** prüft auch **, ob es zur Kompilierungszeit umgewandelt werden kann (= Umwandlung in eine Klasse mit einer Vererbungsbeziehung) **. Es handelt sich also um einen Kompilierungsfehler, nicht um einen Laufzeitfehler!
Code, der im Allgemeinen nicht umgewandelt werden kann, nicht nur Vererbung, führt zu einem Kompilierungsfehler.
Der folgende Code führt zu einem Kompilierungsfehler. Wenn Sie die Mammals-Klasse erben und die Eat-Methode in der Cat-Klasse überschreiben, ist der Offenlegungsbereich strenger als die ursprüngliche Eat-Methode.
class Mammals {
void eat() {}
}
class Cat extends Mammals {
private void eat() {}
}
Im Folgenden werden häufig verwendete Methodenzugriffsmethoden (Zugriffsmodifikatoren) aufgeführt.
//Streng ← Offenlegungsbereich → Lose
private protected /*(Kein Accessor)*/ public
Accessor | Erläuterung |
---|---|
private | Nur innerhalb derselben Klasse verfügbar |
protected | Verfügbar für Klassen im selben Paket oder für Klassen, die die Zielklasse erben |
(Kein Accessor) | Nur in Klassen im selben Paket verfügbar |
public | Erhältlich in jeder Klasse |
Selbst wenn Sie es erben, können Sie es nicht erben ** Private Felder und Methoden (einschließlich Konstruktoren) ** ist!
Oben sagte ich: "Selbst wenn Sie erben, kann der Konstruktor nicht geerbt werden", aber es gibt etwas zu beachten. Das heißt, ** der Konstruktor der Oberklasse wird ausgeführt **, bevor der Konstruktor der Unterklasse ausgeführt wird.
Siehe den Code unten. Es gibt Klassen A, B, C, in denen C B und B A erbt. In jedem Konstruktor wird der Klassenname an die Konsole ausgegeben (der Code wird in einigen verschiedenen Formaten aus Referenz 2 zitiert).
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
}
}
Und hast du gesehen, was passiert, wenn du dieses main () ausführst ... Ja, ** A-, B-, C-Konstruktoren laufen alle! !! ** ** **
... Es tut mir leid, ich habe übertrieben [^ 30].
Die ganze Erklärung ist, warum dies passiert, aber ich möchte aus Referenz 3 S.429 zitieren.
In Java gilt die Regel:" Alle Konstruktoren müssen zu Beginn den Konstruktor des inneren Instanzteils (= übergeordnete Klasse) aufrufen. "
[^ 35]
Mit anderen Worten, unter Berücksichtigung des tatsächlichen Erscheinungsbilds und der Ausführungsreihenfolge des vorherigen Codes
A.java
class A {
public A() {
System.out.print("A"); // 3
}
}
class B extends A {
public B() {
super(); //Rufen Sie den Konstruktor von A 2 auf
System.out.print("B"); // 4
}
}
class C extends B {
public C() {
super(); //Rufen Sie den Konstruktor 1 von B auf
System.out.print("C"); // 5
}
}
public class Main {
public static void main(String[] args) {
new C(); //C 0 instanziieren
}
}
Wenn B () ausgeführt wird, wenn C () aufgerufen wird, wird A () innerhalb von B () usw. aufgerufen, und so erbt die erbende Klasse eine andere Klasse. Versuche zuerst, den Konstruktor der geerbten Klasse auszuführen.
Wenn Sie innerhalb der Unterklasse den Konstruktor der Oberklassenklasse nicht aufgerufen haben, fügt der Compiler automatisch super ()
[^ 37] [^ 40] hinzu!
Jedoch,
super ()
oder super (str)
)this ()
oder this (str)
)
Wenn Sie dies auch tun, fügt der Compiler "super ()" nicht alleine hinzu.Unterklassenkonstruktoren nennen Superklassenkonstruktoren ... Selbst wenn Sie das wissen, werden Sie enttäuscht sein, wenn Sie den Konstruktor einer Klasse aufrufen, die oft so geerbt wird.
In Verbindung mit "02. Beachten Sie die Ausführungsreihenfolge der Konstruktoren" erscheint auch ein solcher Trigger. das ist, ** Code, der den Superklassenkonstruktor doppelt aufruft, führt zu einem Kompilierungsfehler ** darüber.
Schauen Sie sich zunächst den folgenden Code an! (Siehe Referenz 2, S. 362-363, mit einigen Formatänderungen)
Säugetierklasse
public class Mammals {
String name;
int age;
public Mammals(String name, int age) {
this.name = name;
this.age = age;
}
}
Katzenklasse
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);
}
}
Hauptklasse
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 + ", " + "" + "")
}
}
Was halten Sie von diesem Code, dem Compiler?
Die richtige Antwort ist ein Kompilierungsfehler in den Zeilen 3 und 8 der cat class
!
Um zu sehen warum, nehmen wir an, dass dieser Code ausgeführt wurde und folgen dem Prozess für jede generierte Instanz!
① Prozess zum Generieren der cat1
-Instanz
Da es ein Argument wie "Cat cat1 = new Cat (" white ");" gibt, wird "publip Cat (String color)" ausgeführt.
Vor ... erbt Cat von Mammals, sodass der Konstruktor von Mammals ausgeführt wird.
String color
publip Cat(String color) {
super(); //Wird beim Kompilieren automatisch hinzugefügt
this.color = color;
}
Die Mammals-Klasse verfügt jedoch nicht über einen Konstruktor ohne Argumente public Mammals ();
!
Wenn Sie versuchen, eine nicht vorhandene Methode auszuführen, wird in der Zeile "publip Cat (String color)" [^ 45] ein Fehler angezeigt.
② Prozess zum Generieren der cat2
-Instanz
Dieses Mal erstellen wir eine Instanz mit 3 Argumenten.
Daher wird der entsprechende Konstruktor unten ausgeführt!
public Cat(String name, int num, String color) {
super(name, num);
this(color);
}
Zunächst wird der Superklassenkonstruktor "publip Cat (String color)" ausgeführt. Dies ist kein Problem, wie es existiert.
Aber der Code in der nächsten Zeile, diesmal mit dem Cat-Klassenkonstruktor "publip Cat (String color)". Ich denke, dass der gleiche Fehler wie in ① auftreten wird, aber ich werde in eine andere Art von Kompilierungsfehler geraten.
Der Grund ist, dass Sie den Konstruktor der Oberklasse zweimal aufrufen werden.
In Java ist es nicht möglich, den überladenen Konstruktor nach dem Aufruf des Konstrukts der Oberklasse aufzurufen. `[^ 50]
Dieses Mal ist "publip Cat (String color)" der überladene Konstruktor. Dies geschah nach super ();
, was zu einem Fehler führte.
Im eigentlichen Test im Konstruktor
super();
this();
Wenn ich mir den Code ansehe, erhalte ich einen Kompilierungsfehler im Teil this ();
! Es scheint gut zu erinnern!
Vielen Dank für das Lesen bis zum Ende.
[^ 5]: Normalerweise sagt es Ihnen der Editor oder Compiler, es spielt also keine Rolle, ob Sie es nicht verstehen, aber wenn Sie es selbst bemerken müssen, können Sie das nicht sagen! Es bedeutet. [^ 20]: Abgesehen davon können abstrakte Methoden nur in abstrakten Klassen definiert werden. Wenn Sie die Methode nicht in der Cat-Klasse implementieren, empfiehlt es sich, auch die Cat-Klasse anzuhängen. [^ 30]: Ich habe es übertrieben geschrieben. [^ 35]: Referenz 3 Ab S.429 [^ 37]: Es ist nicht so, dass der Code alleine erscheint. Der Code wird nur in dem in super () geschriebenen Text kompiliert. [^ 40]: Erstens handelt es sich um eine Interpretation, ob Sie den Konstruktor der Superklasse ausführen müssen. Wenn der Konstruktor jedoch eine Methode zum Generieren dieser Klasse ist, ist dies die Basis vor dem Erstellen der Unterklasse. Ist es ein Ort, an dem Sie sich auf die Klasse vorbereiten müssen, in der Sie sich befinden (= Superklasse)? [^ 45]: Der Java-Compiler prüft auch, ob die Methode, die Sie ausführen möchten, vorhanden ist, sodass sie als Kompilierungsfehler behandelt wird! [^ 50]: Referenz 2 Ab S.416
Recommended Posts