CodeGym/Java-Blog/Random-DE/Beispiele für die Vererbung verschachtelter Klassen
Autor
Oleksandr Miadelets
Head of Developers Team at CodeGym

Beispiele für die Vererbung verschachtelter Klassen

Veröffentlicht in der Gruppe Random-DE
Hallo! Heute schauen wir uns einen wichtigen Mechanismus an: die Vererbung in verschachtelten Klassen. Haben Sie jemals darüber nachgedacht, was Sie tun würden, wenn Sie eine verschachtelte Klasse dazu bringen müssten, eine andere Klasse zu erben? Wenn nicht, glauben Sie mir: Diese Situation kann verwirrend sein, weil es viele Nuancen gibt.
  1. Lassen wir eine verschachtelte Klasse eine Klasse erben? Oder lassen wir eine Klasse eine verschachtelte Klasse erben?
  2. Ist die untergeordnete/übergeordnete Klasse eine gewöhnliche öffentliche Klasse oder auch eine verschachtelte Klasse?
  3. Welche Art von verschachtelten Klassen verwenden wir schließlich in all diesen Situationen?
Auf all diese Fragen gibt es so viele mögliche Antworten, dass einem der Kopf schwirren wird :) Wie Sie wissen, können wir ein komplexes Problem lösen, indem wir es in einfachere Teile zerlegen. Lass uns das tun. Betrachten wir jede Gruppe verschachtelter Klassen der Reihe nach aus zwei Perspektiven: Wer kann jeden Typ verschachtelter Klasse erben und wer kann er erben? Beginnen wir mit statisch verschachtelten Klassen.

Statisch verschachtelte Klassen

Beispiele für die Vererbung verschachtelter Klassen - 2Ihre Vererbungsregeln sind die einfachsten. Hier können Sie fast alles tun, was Ihr Herz begehrt. Eine statisch verschachtelte Klasse kann Folgendes erben:
  • eine gewöhnliche Klasse
  • eine statisch verschachtelte Klasse, die in einer äußeren Klasse oder ihren Vorgängern deklariert wird
Erinnern Sie sich an ein Beispiel aus unserer Lektion über statisch verschachtelte Klassen.
public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

       public static int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
Versuchen wir, den Code zu ändern und eine Drawingstatische verschachtelte Klasse und ihren Nachkommen zu erstellen – Boeing737Drawing.
public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

   }

   public static class Boeing737Drawing extends Drawing {

       public static int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
Wie Sie sehen, kein Problem. Wir können die Klasse sogar herausziehen Drawingund sie zu einer gewöhnlichen öffentlichen Klasse anstelle einer statischen verschachtelten Klasse machen – es wird sich nichts ändern.
public class Drawing {

}

public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Boeing737Drawing extends Drawing {

       public static int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
Wir verstehen das. Aber welche Klassen können eine statisch verschachtelte Klasse erben? Praktisch alle! Verschachtelt/nicht verschachtelt, statisch/nicht statisch – das spielt keine Rolle. Hier lassen wir die Boeing737Drawinginnere Klasse die Drawingstatische verschachtelte Klasse erben:
public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

   }

   public class Boeing737Drawing extends Drawing {

       public int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
Sie können eine Instanz wie Boeing737Drawingfolgt erstellen:
public class Main {

   public static void main(String[] args) {

      Boeing737 boeing737 = new Boeing737(1990);
      Boeing737.Boeing737Drawing drawing = boeing737.new Boeing737Drawing();
      System.out.println(drawing.getMaxPassengersCount());

   }

}
Obwohl unsere Boeing737DrawingKlasse eine statische Klasse erbt, ist sie selbst nicht statisch! Daher wird immer eine Instanz der äußeren Klasse benötigt. Wir können die Boeing737DrawingKlasse aus der Boeing737Klasse entfernen und sie zu einer einfachen öffentlichen Klasse machen. Nichts verändert sich. Es kann weiterhin die Drawingstatische verschachtelte Klasse erben.
public class Boeing737 {

   private int manufactureYear;
   public static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

   }
}

public class Boeing737Drawing extends Boeing737.Drawing {

   public int getMaxPassengersCount() {

       return Boeing737.maxPassengersCount;

}
Der einzig wichtige Punkt ist, dass wir in diesem Fall die statische Variable öffentlich machen müssen maxPassengersCount. Wenn es privat bleibt, hat eine normale öffentliche Klasse keinen Zugriff darauf. Wir haben statische Klassen herausgefunden! :) Kommen wir nun zu den inneren Klassen. Es gibt drei Typen: einfache innere Klassen, lokale Klassen und anonyme innere Klassen. Beispiele für die Vererbung verschachtelter Klassen – 3Gehen wir noch einmal vom Einfachen zum Komplexen :)

Anonyme innere Klassen

Eine anonyme innere Klasse kann keine andere Klasse erben. Keine andere Klasse kann eine anonyme Klasse erben. Einfacher geht es nicht! :) :)

Lokale Klassen

Lokale Klassen (falls Sie es vergessen haben) werden innerhalb eines Codeblocks einer anderen Klasse deklariert. Am häufigsten geschieht dies innerhalb einer Methode der äußeren Klasse. Logischerweise können nur andere lokale Klassen innerhalb derselben Methode (oder desselben Codeblocks) eine lokale Klasse erben. Hier ist ein Beispiel:
public class PhoneNumberValidator {

   public void validatePhoneNumber(final String number) {

       class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }

           public String getPhoneNumber() {
               return phoneNumber;
           }

           public void setPhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

       class CellPhoneNumber extends PhoneNumber {

       }

       class LandlinePhoneNumber extends PhoneNumber {


       }

       // ...number validation code
   }
}
Dies ist der Code aus unserer Lektion über lokale Klassen. Unsere Nummernvalidatorklasse verfügt über eine PhoneNumberlokale Klasse. Wenn wir zwei unterschiedliche Einheiten darstellen müssen, beispielsweise eine Mobiltelefonnummer und eine Festnetznummer, können wir dies nur innerhalb derselben Methode tun. Der Grund ist einfach: Der Gültigkeitsbereich einer lokalen Klasse ist auf die Methode (Codeblock) beschränkt, in der sie deklariert ist. Daher können wir es nicht extern verwenden (auch nicht für die Klassenvererbung). Allerdings sind die Möglichkeiten der Vererbung innerhalb der lokalen Klasse selbst viel größer! Eine lokale Klasse kann Folgendes erben:
  1. Eine gewöhnliche Klasse.
  2. Eine innere Klasse, die in derselben Klasse wie die lokale Klasse oder in einem ihrer Vorfahren deklariert ist.
  3. Eine andere lokale Klasse, die in derselben Methode (Codeblock) deklariert wurde.
Der erste und dritte Punkt sehen offensichtlich aus, aber der zweite ist etwas verwirrend :/ Schauen wir uns zwei Beispiele an. Beispiel 1 – „Eine lokale Klasse dazu bringen, eine innere Klasse zu erben, die in derselben Klasse wie die lokale Klasse deklariert ist“:
public class PhoneNumberValidator {

   class PhoneNumber {

       private String phoneNumber;

       public PhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }

       public String getPhoneNumber() {
           return phoneNumber;
       }

       public void setPhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }
   }

   public void validatePhoneNumber(final String number) {

       class CellPhoneNumber extends PhoneNumber {

           public CellPhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       class LandlinePhoneNumber extends PhoneNumber {

           public LandlinePhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       // ...number validation code
   }
}
Hier haben wir die PhoneNumberKlasse aus der validatePhoneNumber()Methode entfernt und sie zu einer inneren Klasse anstelle einer lokalen Klasse gemacht. Dies hindert uns nicht daran, unsere beiden lokalen Klassen dazu zu bringen, es zu erben. Beispiel 2 – „... oder in den Vorfahren dieser Klasse.“ Das ist jetzt schon interessanter. Wir können PhoneNumberin der Vererbungskette noch weiter nach oben vordringen. Lassen Sie uns eine abstrakte AbstractPhoneNumberValidatorKlasse deklarieren, die zum Vorfahren unserer PhoneNumberValidatorKlasse wird:
public abstract class AbstractPhoneNumberValidator {

   class PhoneNumber {

       private String phoneNumber;

       public PhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }

       public String getPhoneNumber() {
           return phoneNumber;
       }

       public void setPhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }
   }

}
Wie Sie sehen, haben wir es nicht nur deklariert, sondern auch die PhoneNumberinnere Klasse hinein verschoben. PhoneNumberValidatorIn seinem Nachkommen können in Methoden deklarierte lokale Klassen jedoch PhoneNumberproblemlos erben!
public class PhoneNumberValidator extends AbstractPhoneNumberValidator {

   public void validatePhoneNumber(final String number) {

       class CellPhoneNumber extends PhoneNumber {

           public CellPhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       class LandlinePhoneNumber extends PhoneNumber {

           public LandlinePhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       // ...number validation code
   }
}
Aufgrund der Vererbungsbeziehung „sehen“ die lokalen Klassen innerhalb einer Nachkommenklasse die inneren Klassen innerhalb eines Vorfahren. Und zum Schluss kommen wir zur letzten Gruppe :)

Innere Klassen

Eine innere Klasse, die in derselben äußeren Klasse (oder in ihrem Nachkommen) deklariert ist, kann eine andere innere Klasse erben. Lassen Sie uns dies anhand unseres Beispiels mit Fahrrädern aus der Lektion über innere Klassen untersuchen.
public class Bicycle {

   private String model;
   private int maxWeight;

   public Bicycle(String model, int maxWeight) {
       this.model = model;
       this.maxWeight = maxWeight;
   }

   public void start() {
       System.out.println("Let's go!");
   }

   class Seat {

       public void up() {

           System.out.println("Seat up!");
       }

       public void down() {

           System.out.println("Seat down!");
       }
   }

   class SportSeat extends Seat {

       // ...methods
   }
}
Hier haben wir die Seatinnere Klasse innerhalb der BicycleKlasse deklariert. Eine besondere Art von Rennsitz, SportSeaterbt es. Aber wir könnten einen separaten „Rennrad“-Typ erstellen und ihn einer separaten Klasse zuordnen:
public class SportBicycle extends Bicycle {

   public SportBicycle(String model, int maxWeight) {
       super(model, maxWeight);
   }


   class SportSeat extends Seat {

       public void up() {

           System.out.println("Seat up!");
       }

       public void down() {

           System.out.println("Seat down!");
       }
   }
}
Dies ist auch eine Option. Die innere Klasse des Nachkommen ( SportBicycle.SportSeat) „sieht“ die inneren Klassen des Vorfahren und kann sie erben. Das Erben innerer Klassen hat eine sehr wichtige Funktion! In den beiden vorherigen Beispielen SportSeatwar unsere Klasse eine innere Klasse. SportSeatWas aber, wenn wir uns entscheiden , eine gewöhnliche öffentliche Klasse zu erstellen , die gleichzeitig die Seatinnere Klasse erbt?
// Error! No enclosing instance of type 'Bicycle' is in scope
class SportSeat extends Bicycle.Seat {

   public SportSeat() {

   }

   public void up() {

       System.out.println("Seat up!");
   }

   public void down() {

       System.out.println("Seat down!");
   }
}
Es ist ein Fehler aufgetreten! Kannst du erraten warum? :) Es ist alles unkompliziert. Als wir über die Bicycle.Seatinnere Klasse sprachen, erwähnten wir, dass ein Verweis auf eine Instanz der äußeren Klasse implizit an den Konstruktor der inneren Klasse übergeben wird. Das bedeutet, dass Sie kein SeatObjekt erstellen können, ohne ein BicycleObjekt zu erstellen. Aber wie sieht es mit der Schaffung eines aus SportSeat? Im Gegensatz zu Seatverfügt es nicht über diesen integrierten Mechanismus, um dem Konstruktor implizit einen Verweis auf eine Instanz der äußeren Klasse zu übergeben. Dennoch Bicyclekönnen wir ohne ein Objekt kein SportSeatObjekt erschaffen, genau wie im Fall von Seat. Daher bleibt uns nur noch eines zu tun – dem SportSeatKonstruktor explizit eine Referenz auf ein BicycleObjekt zu übergeben. So geht's:
class SportSeat extends Bicycle.Seat {

   public SportSeat(Bicycle bicycle) {

       bicycle.super();
   }

   public void up() {

       System.out.println("Seat up!");
   }

   public void down() {

       System.out.println("Seat down!");
   }
}
Wir rufen den Superklassenkonstruktor mit auf super(); . Wenn wir nun ein Objekt erstellen möchten SportSeat, hindert uns nichts daran, dies zu tun:
public class Main {

   public static void main(String[] args) {

       Bicycle bicycle = new Bicycle("Peugeot", 120);
       SportSeat peugeotSportSeat = new SportSeat(bicycle);

   }
}
Puh! Diese Lektion war ziemlich lang :) Aber du hast viel gelernt! Jetzt ist es an der Zeit, einige Aufgaben zu lösen! :) :)
Kommentare
  • Beliebt
  • Neu
  • Alt
Du musst angemeldet sein, um einen Kommentar schreiben zu können
Auf dieser Seite gibt es noch keine Kommentare