Hallo! Lassen Sie uns über abstrakte Klassen in Java sprechen.Konkrete Beispiele für abstrakte Klassen in Java - 1

Warum heißen Klassen „abstrakt“?

Sie erinnern sich wahrscheinlich noch daran, was Abstraktion ist – wir haben es bereits besprochen :) Wenn Sie es vergessen haben, machen Sie sich keine Sorgen. Denken Sie daran, dass es sich um ein OOP-Prinzip handelt , das besagt, dass Sie beim Entwerfen von Klassen und Erstellen von Objekten nur die Haupteigenschaften der Entität darstellen und sekundäre Eigenschaften verwerfen sollten. Wenn wir beispielsweise eine SchoolTeacherKlasse entwerfen, wird die Körpergröße wahrscheinlich keine notwendige Eigenschaft eines Lehrers sein. Tatsächlich ist diese Eigenschaft für einen Lehrer nicht wichtig. Wenn wir jedoch eine BasketballPlayerKlasse erstellen, ist die Größe eines der wichtigsten Merkmale. Nun, eine abstrakte Klasseist das abstrakteste, „grobeste Werkstück“ für eine Gruppe zukünftiger Klassen. Das Werkstück kann nicht direkt verwendet werden, da es zu „rau“ ist. Aber es definiert bestimmte charakteristische Zustände und Verhaltensweisen, die zukünftige Klassen – die Nachkommen der abstrakten Klasse – haben werden.

Beispiele für abstrakte Klassen in Java

Betrachten Sie ein einfaches Beispiel mit Autos:

public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;
  
   public abstract void gas();

   public abstract void brake();

   public String getModel() {
       return model;
   }

   public void setModel(String model) {
       this.model = model;
   }

   public String getColor() {
       return color;
   }

   public void setColor(String color) {
       this.color = color;
   }

   public int getMaxSpeed() {
       return maxSpeed;
   }

   public void setMaxSpeed(int maxSpeed) {
       this.maxSpeed = maxSpeed;
   }
}
So sieht die einfachste abstrakte Klasse aus. Wie Sie sehen, nichts Besonderes :) Warum könnten wir das brauchen? Erstens bietet es die abstrakteste Beschreibung der Entität, die wir brauchen – ein Auto. Das abstrakte Schlüsselwort bedeutet hier etwas. In der realen Welt gibt es nicht „nur ein Auto“. Es gibt Lastwagen, Rennwagen, Limousinen, Coupés und SUVs. Unsere abstrakte Klasse ist einfach eine „Blaupause“, die wir später verwenden werden, um bestimmte Fahrzeugklassen zu erstellen.

public class Sedan extends Car {
  
   @Override
   public void gas() {
       System.out.println("The sedan is accelerating!");
   }

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }
  
}
In vielerlei Hinsicht ähnelt dies dem, worüber wir in den Lektionen zum Thema Vererbung gesprochen haben. Nur in diesem Fall hatten wir eine CarKlasse, deren Methoden nicht abstrakt waren. Eine solche Lösung hat jedoch mehrere Nachteile, die in abstrakten Klassen behoben werden. Erstens kann keine Instanz einer abstrakten Klasse erstellt werden:

public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
Der Entwickler von Java hat dieses „Feature“ mit Absicht entwickelt. Denken Sie noch einmal daran: Eine abstrakte Klasse ist nur eine Blaupause für zukünftige „reguläre“ Klassen . Sie brauchen keine Kopien eines Bauplans, oder? Ebenso besteht keine Notwendigkeit, Instanzen einer abstrakten Klasse zu erstellen :) Und wenn die CarKlasse nicht abstrakt wäre, könnten wir problemlos Instanzen davon erstellen:

public class Car {

   private String model;
   private String color;
   private int maxSpeed;
  
   public void go() {
       // ...some logic
   }

   public  void brake() {
       // ...some logic
   }
}


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // This is okay. The car is created.
   }
}
Derzeit hat unser Programm eine Art unverständliches Auto. Es ist kein LKW, kein Rennwagen und keine Limousine, aber es ist nicht wirklich klar, was es ist. Es ist das „nur ein Auto“, das in der Realität nicht existiert. Das gleiche Beispiel lässt sich auch bei Tieren anführen. Stellen Sie sich vor, Ihr Programm hätte AnimalObjekte („ nur Tiere “). Es ist nicht klar, um welche Art es sich handelt, zu welcher Familie es gehört oder welche Eigenschaften es hat. Es wäre seltsam, einen in einem Programm zu sehen. In der Natur gibt es keine „gerechten Tiere“. Nur Hunde, Katzen, Füchse, Maulwürfe usw. Abstrakte Klassen bewahren uns vor „ nur Objekten “. Sie geben uns den Grundzustand und das Verhalten vor. Beispielsweise müssen alle Autos ein Modell , eine Farbe und eine Höchstgeschwindigkeit habenAußerdem müssen sie in der Lage sein, Gas zu geben und zu bremsen . Das ist es. Es handelt sich um einen allgemeinen abstrakten Entwurf, den Sie später zum Entwerfen der benötigten Klassen verwenden. Hinweis: Die beiden Methoden in der abstrakten Klasse sind ebenfalls abstrakt , was bedeutet, dass sie überhaupt keine Implementierung haben. Der Grund ist derselbe: Abstrakte Klassen erstellen kein „Standardverhalten“ für „nur Autos“. Sie geben lediglich vor, was jedes Auto können muss. Wenn Sie jedoch ein Standardverhalten benötigen, können Sie Methoden in einer abstrakten Klasse implementieren. Java verbietet dies nicht:

public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       System.out.println("Accelerating!");
   }

   public abstract void brake();
  
   // Getters and setters
}


public class Sedan extends Car {

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       sedan.gas();
   }
}
Konsolenausgabe:
Accelerating!
Wie Sie sehen, haben wir eine Methode in der abstrakten Klasse implementiert, die andere jedoch nicht. Infolgedessen Sedanist das Verhalten unserer Klasse in zwei Teile unterteilt: Wenn wir ihre gas()Methode aufrufen, wird das Verhalten aus der abstrakten übergeordneten Klasse „heraufgeholt“ Carund wir implementieren die brake()Methode in der SedanKlasse. Das ist super bequem und flexibel. Aber unsere Klasse ist jetzt doch nicht mehr so ​​abstrakt, oder ? Immerhin hat es tatsächlich die Hälfte der Methoden implementiert. Tatsache ist – und das ist ein sehr wichtiges Merkmal –, dass eine Klasse abstrakt ist, wenn auch nur eine ihrer Methoden abstrakt ist. Eine Methode von zwei oder eine von tausend – es spielt keine Rolle. Wir könnten sogar alle Methoden implementieren, sodass keine Abstraktion übrig bleibt. Das Ergebnis wäre eine abstrakte Klasse ohne abstrakte Methoden. Dies ist grundsätzlich möglich – der Compiler erzeugt keine Fehler –, es ist jedoch besser, dies nicht zu tun, da das Wort „abstrakt“ dadurch seiner Bedeutung beraubt wird. Ihre Programmierkollegen werden ebenfalls sehr überrascht sein, dies zu sehen :/ Das heißt, wenn eine Methode als abstrakt markiert ist, muss jede abgeleitete Klasse sie implementieren oder als abstrakt deklariert werden. Andernfalls gibt der Compiler einen Fehler aus. Natürlich kann jede Klasse nur eine abstrakte Klasse erben, sodass es hinsichtlich der Vererbung keinen Unterschied zwischen abstrakten und regulären Klassen gibt. Es spielt keine Rolle, ob wir eine abstrakte oder eine reguläre Klasse erben – es kann nur eine übergeordnete Klasse geben.

Warum Java keine Mehrfachklassenvererbung hat

Wir haben bereits gesagt, dass es in Java keine Mehrfachvererbung gibt, aber wir haben nicht wirklich darauf eingegangen, warum. Versuchen wir das jetzt. Tatsache ist, dass untergeordnete Klassen nicht entscheiden könnten, welches Verhalten sie wählen würden, wenn Java über Mehrfachvererbung verfügen würde. Nehmen wir an, wir haben zwei Klassen: Toasterund NuclearBomb:

public class Toaster {
  
  
 public void on() {

       System.out.println("The toaster is on. We're toasting!");
   }
  
   public void off() {

       System.out.println("The toaster is off!");
   }
}


public class NuclearBomb {

   public void on() {

       System.out.println("Boom!");
   }
}
Wie Sie sehen, verfügen beide Klassen über eine on()Methode. Beim Toaster beginnt die Methode mit dem Toasten, bei der Atombombe löst sie jedoch eine Explosion aus. Uh-oh :/ Stellen Sie sich nun vor, Sie hätten beschlossen (fragen Sie mich nicht warum!), etwas dazwischen zu schaffen. Hier ist deine Klasse: MysteriousDevice! Dieser Code wird natürlich nicht funktionieren. Wir stellen es einfach als Beispiel dafür dar, „was hätte sein können“:

public class MysteriousDevice extends Toster, NuclearBomb {

   public static void main(String[] args) {
      
       MysteriousDevice mysteriousDevice = new MysteriousDevice();
       mysteriousDevice.on(); // And what should happen here? Will we get toast or a nuclear apocalypse?
   }
}
Mal sehen, was wir haben. Das mysteriöse Gerät stammt gleichzeitig von Toaster und NuclearBomb ab. Beide haben eine on()Methode. Daher ist nicht klar, welche Implementierung ausgeführt werden soll, wenn wir on()ein MysteriousDeviceObjekt aufrufen. Das Objekt wird es nicht verstehen. Und um das Ganze abzurunden, verfügt NuclearBomb über keine off()Methode. Wenn wir also nicht richtig raten, ist es unmöglich, das Gerät auszuschalten. Konkrete Beispiele für abstrakte Klassen in Java - 2Dieses „Missverständnis“, bei dem unklar ist, welches Verhalten ausgeführt werden soll, ist genau der Grund, warum die Java-Entwickler die Mehrfachvererbung abgelehnt haben. Allerdings erfahren Sie, dass Java-Klassen viele Schnittstellen implementieren können.