JavaRush /Java-Blog /Random-DE /Kaffeepause Nr. 140. Abstrakte Klassen und Schnittstellen...

Kaffeepause Nr. 140. Abstrakte Klassen und Schnittstellen in Java

Veröffentlicht in der Gruppe Random-DE
Quelle: InfoWorld Heute erfahren Sie, in welchen Fällen ein Entwickler eine abstrakte Klasse und in welchen Fällen ein Interface verwenden sollte. Wir werden auch die Unterschiede zwischen diesen Elementen der Java-Sprache und deren Verwendung in Programmen identifizieren. Kaffeepause Nr. 140.  Abstrakte Klassen und Schnittstellen in Java - 1Abstrakte Klassen und Schnittstellen sind im Java-Code und sogar im Java Development Kit (JDK) selbst weit verbreitet. Jedes dieser Elemente dient einem anderen Zweck:
  • Eine Schnittstelle ist ein Konstrukt in der Java-Sprache, das bei der Implementierung abstrakter Methoden und statischer Konstanten hilft.
  • Abstrakte Klassen ähneln regulären Klassen, außer dass sie abstrakte Methoden enthalten können, also Methoden ohne Körper. Abstrakte Klassen können nicht erstellt werden.
Viele Entwickler denken, dass Schnittstellen und abstrakte Klassen ähnlich sind, aber in Wirklichkeit stimmt das nicht ganz. Schauen wir uns die Hauptunterschiede zwischen ihnen an.

Was ist eine Schnittstelle?

Im Kern handelt es sich bei einer Schnittstelle um einen Vertrag, daher hängt es von der Implementierung ab, den Zweck ihrer Erstellung zu definieren. Die Schnittstelle kann keine veränderlichen Instanzvariablen verwenden, sondern nur endgültige Variablen.

Wann werden Schnittstellen verwendet?

Schnittstellen sind sehr nützlich, um Code zu trennen und Polymorphismus zu implementieren. Wir können dies im JDK mit der List- Schnittstelle sehen :
public interface List<E> extends Collection<E> {

    int size();
    boolean isEmpty();
    boolean add(E e);
    E remove(int index);
    void clear();
}
Wie Sie wahrscheinlich bemerkt haben, ist dieser Code zwar kurz, aber dennoch recht anschaulich. Wir können die Methodensignatur, die zum Implementieren der Methoden in der Schnittstelle mithilfe der konkreten Klasse verwendet wird, leicht erkennen. Die List- Schnittstelle enthält einen Vertrag, der von den Klassen ArrayList , Vector , LinkedList und anderen implementiert werden kann. Um Polymorphismus zu nutzen, können wir einfach den Typ unserer Variablen mit List deklarieren und dann eine der verfügbaren Instanzen auswählen. Hier ist ein weiteres Beispiel:
List list = new ArrayList();
System.out.println(list.getClass());

 List list = new LinkedList();
 System.out.println(list.getClass());
Die Ausgabe ist:
Klasse java.util.ArrayList Klasse java.util.LinkedList
In diesem Fall sind die Implementierungsmethoden für ArrayList , LinkedList und Vector unterschiedlich, was ein hervorragendes Szenario für die Verwendung der Schnittstelle darstellt. Wenn Sie feststellen, dass viele Klassen zu einer übergeordneten Klasse mit denselben Methodenaktionen, aber unterschiedlichem Verhalten gehören. In solchen Situationen empfiehlt sich die Nutzung der Schnittstelle. Schauen wir uns als Nächstes verschiedene Optionen für die Verwendung von Schnittstellen an.

Überschreiben der Schnittstellenmethode

Wie wir bereits wissen, ist eine Schnittstelle eine Art Vertrag, der von einer konkreten Klasse implementiert werden muss. Schnittstellenmethoden sind implizit abstrakt und erfordern eine konkrete Implementierung der Klasse. Hier ist ein Beispiel:
public class OverridingDemo {
  public static void main(String[] args) {
    Challenger challenger = new JavaChallenger();
    challenger.doChallenge();
  }
}

interface Challenger {
  void doChallenge();
}

class JavaChallenger implements Challenger {
  @Override
  public void doChallenge() {
    System.out.println("Challenge done!");
  }
}
Abschluss:
Herausforderung geschafft!
Beachten Sie, dass Schnittstellenmethoden implizit abstrakt sind. Das bedeutet, dass wir sie nicht explizit als abstrakt deklarieren müssen.

Konstante Variablen

Eine weitere zu beachtende Regel ist, dass eine Schnittstelle nur konstante Variablen enthalten kann. Hier ist ein Beispiel:
public class Challenger {

  int number = 7;
  String name = "Java Challenger";

}
Hier sind beide Variablen implizit final und static . Das heißt, sie sind konstant, unabhängig von der Instanz und können nicht geändert werden. Jetzt werden wir versuchen, die Variablen in der Challenger- Schnittstelle zu ändern , sagen wir so:
Challenger.number = 8;
Challenger.name = "Another Challenger";
Dies führt zu einem Kompilierungsfehler:
Der endgültigen Variablen „Nummer“ kann kein Wert zugewiesen werden. Der endgültigen Variablen „Name“ kann kein Wert zugewiesen werden.

Standardmethoden

Als in Java 8 Standardmethoden eingeführt wurden, dachten einige Entwickler, sie seien mit abstrakten Klassen identisch. Dies trifft jedoch nicht zu, da Schnittstellen keinen Status haben können. Eine Standardmethode kann eine Implementierung haben, abstrakte Methoden jedoch nicht. Standardmethoden sind das Ergebnis von Innovationen mit Lambda-Ausdrücken und -Streams, wir müssen sie jedoch mit Vorsicht verwenden. Die Methode im JDK, die die Standardmethode verwendet, ist forEach() , die Teil der Iterable- Schnittstelle ist . Anstatt den Code in jede Iterable- Implementierung zu kopieren, können wir einfach die forEach- Methode wiederverwenden :
default void forEach(Consumer<? super T> action) {
  // Code implementation here...
Jede Iterable- Implementierung kann die Methode forEach() verwenden , ohne dass eine neue Methodenimplementierung erforderlich ist. Anschließend können wir den Code mit der Standardmethode wiederverwenden. Lassen Sie uns unsere eigene Standardmethode erstellen:
public class DefaultMethodExample {

  public static void main(String[] args) {
    Challenger challenger = new JavaChallenger();
    challenger.doChallenge();
  }

}

class JavaChallenger implements Challenger { }

interface Challenger {

  default void doChallenge() {
    System.out.println("Challenger doing a challenge!");
  }
}
Ergebnis:
Herausforderer macht eine Herausforderung!
Im Hinblick auf Standardmethoden ist es wichtig zu beachten, dass jede dieser Methoden implementiert werden muss. Die Standardmethode kann nicht statisch sein. Kommen wir nun zu den abstrakten Klassen.

Die Essenz einer abstrakten Klasse

Abstrakte Klassen können einen Zustand mit Instanzvariablen haben. Dies bedeutet, dass die Instanzvariable verwendet und geändert werden kann. Hier ist ein Beispiel:
public abstract class AbstractClassMutation {

  private String name = "challenger";

  public static void main(String[] args) {
    AbstractClassMutation abstractClassMutation = new AbstractClassImpl();
    abstractClassMutation.name = "mutated challenger";
    System.out.println(abstractClassMutation.name);
  }

}

class AbstractClassImpl extends AbstractClassMutation { }
Abschluss:
mutierter Herausforderer

Abstrakte Methoden in abstrakten Klassen

Abstrakte Klassen können wie Schnittstellen abstrakte Methoden haben. Eine abstrakte Methode ist eine Methode ohne Körper. Im Gegensatz zu Schnittstellen müssen abstrakte Methoden in abstrakten Klassen explizit als abstrakt deklariert werden. Hier ist ein Beispiel:
public abstract class AbstractMethods {

  abstract void doSomething();

}
Und hier ist ein Versuch, eine Methode ohne Implementierung und ohne das Schlüsselwort abstract zu deklarieren :
public abstract class AbstractMethods {
   void doSomethingElse();
}
Leider führt dies zu einem Kompilierungsfehler:
Fehlender Methodenkörper oder Zusammenfassung deklariert

Wann sollten abstrakte Klassen verwendet werden?

Eine abstrakte Klasse wird empfohlen, wenn Sie einen veränderlichen Zustand implementieren müssen. Beispielsweise enthält das Java Collections Framework eine AbstractList- Klasse , die den Status von Variablen verwendet. In Fällen, in denen Sie den Klassenstatus nicht verwalten müssen, ist es normalerweise besser, eine Schnittstelle zu verwenden.

Unterschiede zwischen abstrakten Klassen und Schnittstellen

Aus Sicht der objektorientierten Programmierung besteht der Hauptunterschied zwischen einer Schnittstelle und einer abstrakten Klasse darin, dass eine Schnittstelle keinen Status haben kann, wohingegen eine abstrakte Klasse einen Status mit Instanzvariablen haben kann. Ein weiterer wesentlicher Unterschied besteht darin, dass Klassen mehr als eine Schnittstelle implementieren, aber nur eine abstrakte Klasse erweitern können. Diese Lösung basiert auf der Tatsache, dass Mehrfachvererbung (Erweitern von mehr als einer Klasse) zu einem Code-Deadlock führen kann. Die Entwickler der Java-Sprache haben beschlossen, dies zu vermeiden. Ein weiterer Unterschied besteht darin, dass Schnittstellen durch Klassen implementiert oder durch Schnittstellen erweitert werden können, Klassen jedoch nur erweitert werden können. Es ist wichtig zu beachten, dass Lambda-Ausdrücke nur mit einer funktionalen Schnittstelle (also einer Schnittstelle mit nur einer Methode) verwendet werden können, während abstrakte Klassen mit nur einer abstrakten Methode keine Lambda-Ausdrücke verwenden können. Hier sind einige weitere Unterschiede zwischen abstrakten Klassen und Schnittstellen. Schnittstelle:
  • Kann nur endgültige statische Variablen haben. Eine Schnittstelle kann niemals ihren eigenen Zustand ändern.
  • Eine Klasse kann mehrere Schnittstellen implementieren.
  • Kann mit dem Schlüsselwort „implements“ implementiert werden. Eine Schnittstelle kann eine andere Schnittstelle erweitern.
  • Methoden können nur statische Endfelder, Parameter oder lokale Variablen verwenden.
  • Nur funktionale Schnittstellen können die Lambda-Funktion in Java verwenden.
  • Kann keinen Konstruktor haben.
  • Kann abstrakte Methoden haben.
  • Kann Standard- und statische Methoden haben (eingeführt in Java 8).
  • Kann private Methoden mit Implementierung haben (eingeführt in Java 9).
Abstrakte Klassen:
  • Kann beliebige Instanzen oder statische Variablen haben, veränderbar oder unveränderlich.
  • Eine Klasse kann nur eine abstrakte Klasse erweitern.
  • Kann eine Instanz veränderlicher Felder, Parameter oder lokaler Variablen enthalten.
  • Abstrakte Klassen mit nur einer abstrakten Methode können keine Lambda-Ausdrücke verwenden.
  • Kann einen Konstruktor haben.
  • Kann beliebige Methoden haben.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION