wake-up-neo.com

Abstrakte Klasse gegen Schnittstelle in Java

Mir wurde eine Frage gestellt, ich wollte meine Antwort hier überprüfen lassen.

Q: In welchem ​​Szenario ist es sinnvoller, eine abstrakte Klasse zu erweitern, anstatt die Schnittstelle (n) zu implementieren?

A: Wenn wir ein Muster für die Mustermethode verwenden.

Hab ich recht ?

Es tut mir leid, wenn ich die Frage nicht klar formulieren konnte.
Ich kenne den grundlegenden Unterschied zwischen abstrakter Klasse und Schnittstelle.

1) Verwenden Sie eine abstrakte Klasse, wenn die Anforderung so ist, dass wir für jede bestimmte Operation dieselbe Funktionalität in jeder Unterklasse implementieren müssen (implementieren Sie die Methode) und für einige andere Operationen (nur Methodensignaturen) unterschiedliche Funktionen. 

2) Verwenden Sie die Schnittstelle, wenn Sie die Signatur gleich setzen müssen (und die Implementierung unterschiedlich ist), damit Sie die Schnittstellenimplementierung einhalten können 

3) wir können max von einer abstrakten Klasse erweitern, können jedoch mehr als eine Schnittstelle implementieren 

Wiederholung der Frage: Gibt es neben den oben genannten Szenarien noch andere Szenarien, in denen speziell die Verwendung von abstrakten Klassen erforderlich ist (eines davon ist das Muster-Entwurfsmuster, das nur konzeptuell darauf basiert)?

Schnittstelle vs. abstrakte Klasse

Die Wahl zwischen diesen beiden Optionen hängt wirklich davon ab, was Sie tun möchten, aber zum Glück kann Erich Gamma uns ein bisschen helfen.

Wie immer gibt es einen Kompromiss, eine Schnittstelle gibt Ihnen Freiheit in Bezug auf die Basisklasse, eine abstrakte Klasse gibt Ihnen die Freiheit, später neue Methoden hinzuzufügen. - Erich Gamma

Sie Sie können ein Interface nicht ändern, ohne viele andere Dinge ändern zu müssen in Ihrem Code. Daher können Sie dies nur vermeiden, indem Sie ein ganz neues Interface erstellen, das möglicherweise nicht immer eine ist gute Sache.

Abstract classes sollte in erster Linie für eng verwandte Objekte verwendet werden. Interfaces bietet eine bessere Funktionalität für nicht verbundene Klassen.

73
Java Geek

Wann werden Schnittstellen verwendet?

Mit einer Schnittstelle kann jemand von vorne anfangen, um Ihre Schnittstelle zu implementieren oder Ihre Schnittstelle in einen anderen Code zu implementieren, dessen ursprünglicher oder primärer Zweck sich stark von Ihrer Schnittstelle unterscheidet. Für sie ist Ihre Schnittstelle nur zufällig, etwas, das zu ihrem Code hinzugefügt werden muss, um Ihr Paket verwenden zu können. Der Nachteil ist, dass jede Methode in der Schnittstelle öffentlich sein muss. Sie möchten vielleicht nicht alles aufdecken.

Wann werden abstrakte Klassen verwendet?

Eine abstrakte Klasse dagegen bietet mehr Struktur. Es definiert normalerweise einige Standardimplementierungen und stellt einige Werkzeuge bereit, die für eine vollständige Implementierung nützlich sind. Der Haken ist, dass der Code, in dem er verwendet wird, Ihre Klasse als Basis verwenden muss. Dies kann sehr unpraktisch sein, wenn die anderen Programmierer, die Ihr Paket verwenden möchten, bereits eine eigene Klassenhierarchie entwickelt haben. In Java kann eine Klasse nur von einer Basisklasse erben.

Wann beide verwendet werden

Sie können das Beste aus beiden Welten, eine Schnittstelle und eine abstrakte Klasse anbieten. Implementierer können Ihre abstrakte Klasse ignorieren, wenn sie möchten. Der einzige Nachteil dabei ist der Aufruf von Methoden über ihren Schnittstellennamen etwas langsamer als der Aufruf über ihren abstrakten Klassennamen. 

73
DivineDesert

wiederholt die Frage: Es gibt noch ein anderes Szenario oben erwähnt, wo speziell die Verwendung der abstrakten Klasse .__ erforderlich ist. (Eines ist zu sehen, ist Mustermethode Design-Muster konzeptionell auf .__ nur dies basiert)

Ja, wenn Sie JAXB verwenden. Es mag keine Schnittstellen. Sie sollten entweder abstrakte Klassen verwenden oder diese Einschränkung mit Generika umgehen.

Aus einem persönlichen Blog Post :

Schnittstelle:

  1. Eine Klasse kann mehrere Schnittstellen implementieren
  2. Eine Schnittstelle kann überhaupt keinen Code bereitstellen
  3. Eine Schnittstelle kann nur öffentliche statische Endkonstanten definieren
  4. Eine Schnittstelle kann keine Instanzvariablen definieren
  5. Das Hinzufügen einer neuen Methode hat Auswirkungen auf die Implementierung von Klassen (Entwurfspflege).
  6. JAXB kann nicht mit Schnittstellen umgehen
  7. Eine Schnittstelle kann eine abstrakte Klasse nicht erweitern oder implementieren
  8. Alle Schnittstellenmethoden sind öffentlich

Im Allgemeinen sollten Schnittstellen verwendet werden, um Verträge zu definieren (was soll erreicht werden, nicht wie sie erreicht werden sollen).

Abstrakte Klasse:

  1. Eine Klasse kann höchstens eine abstrakte Klasse erweitern
  2. Eine abstrakte Klasse kann Code enthalten
  3. Eine abstrakte Klasse kann sowohl statische als auch Instanzkonstanten definieren (final)
  4. Eine abstrakte Klasse kann Instanzvariablen definieren
  5. Die Änderung des vorhandenen abstrakten Klassencodes hat Auswirkungen auf die Erweiterung von Klassen (Implementierungspflege).
  6. Das Hinzufügen einer neuen Methode zu einer abstrakten Klasse hat keine Auswirkungen auf das Erweitern von Klassen
  7. Eine abstrakte Klasse kann eine Schnittstelle implementieren
  8. Abstrakte Klassen können private und geschützte Methoden implementieren

Abstrakte Klassen sollten für die (teilweise) Implementierung verwendet werden. Sie können ein Mittel sein, um die Implementierung von API-Verträgen zu beschränken.

25

Die Schnittstelle wird verwendet, wenn Sie ein Szenario haben, bei dem alle Klassen dieselbe Struktur haben, jedoch völlig unterschiedliche Funktionen haben.

Eine abstrakte Klasse wird verwendet, wenn Sie das Szenario haben, dass alle Klassen dieselbe Struktur haben, jedoch einige gleiche und einige unterschiedliche Funktionen.

Schauen Sie sich den Artikel an: http://shoaibmk.blogspot.com/2011/09/abstract-class-is-class-which-cannot-be.html

10
SMK

Welche sollten Sie verwenden, abstrakte Klassen oder Schnittstellen?

Erwägen Sie die Verwendung abstrakter Klassen, wenn eine der folgenden Aussagen für Ihr Szenario gilt:

Sie möchten Code unter mehreren eng miteinander verwandten Klassen teilen.

Sie erwarten, dass Klassen, die Ihre abstrakte Klasse erweitern, viele allgemeine Methoden oder Felder aufweisen oder andere Zugriffsmodifizierer als public (wie protected und private) erfordern.

Sie möchten nicht statische oder nicht abschließende Felder deklarieren. Auf diese Weise können Sie Methoden definieren, die auf den Status des Objekts, zu dem sie gehören, zugreifen und diesen ändern können.

Erwägen Sie die Verwendung von Schnittstellen, wenn eine dieser Aussagen auf Ihre Situation zutrifft:

Sie erwarten, dass nicht verknüpfte Klassen Ihr Interface implementieren. Die Schnittstellen Comparable und Cloneable werden beispielsweise von vielen nicht verwandten Klassen implementiert.

Sie möchten das Verhalten eines bestimmten Datentyps angeben, ohne sich jedoch darum zu kümmern, wer sein Verhalten implementiert.

Sie möchten die Mehrfachvererbung des Typs nutzen.

http://docs.Oracle.com/javase/tutorial/Java/IandI/abstract.html

4
Santh

In den letzten drei Jahren hat sich vieles geändert, und es wurden neue Funktionen für die Schnittstelle zu Java 8 hinzugefügt. 

Aus der Oracle-Dokumentation page on interface:

Eine Schnittstelle ist ähnlich einer Klasse ein Referenztyp, der nur Konstanten, Methodensignaturen, default-Methoden, statische Methoden und verschachtelte Typen enthalten kann. Methodentexte sind nur für Standardmethoden und statische Methoden vorhanden.

Wie Sie in Ihrer Frage zitiert haben, ist die abstrakte Klasse am besten geeignet für Mustermustermuster, wo Sie ein Skelett erstellen müssen. Schnittstelle kann hier nicht verwendet werden.

Eine weitere Überlegung, die abstrakte Klasse der Schnittstelle vorzuziehen:

Sie haben keine Implementierung in der Basisklasse und nur Unterklassen müssen ihre eigene Implementierung definieren. Sie benötigen eine abstrakte Klasse anstelle einer Schnittstelle, da Sie den Status mit Unterklassen gemeinsam nutzen möchten.

Die abstrakte Klasse legt fest, "ist eine" Beziehung zwischen verwandten Klassen und Schnittstellen, die "die Fähigkeit hat", zwischen nicht verbundenen Klassen.


Zum zweiten Teil Ihrer Frage, die für die meisten Programmiersprachen gilt, einschließlich Java vor Java-8

Wie immer gibt es einen Kompromiss, eine Schnittstelle gibt Ihnen die Freiheit in Bezug auf die Basisklasse, eine abstrakte Klasse gibt Ihnen die Freiheit, später neue Methoden hinzuzufügen. - Erich Gamma

Sie können eine Schnittstelle nicht ändern, ohne viele andere Dinge in Ihrem Code ändern zu müssen

Wenn Sie es bevorzugen, dass abstrakte Klassen früher mit den obigen zwei Überlegungen verwendet werden, müssen Sie jetzt erneut darüber nachdenken, dass Standardmethoden Schnittstellen über leistungsstarke Funktionen verfügen. 

Mithilfe von Standardmethoden können Sie den Schnittstellen Ihrer Bibliotheken neue Funktionen hinzufügen und die binäre Kompatibilität mit Code sicherstellen, der für ältere Versionen dieser Schnittstellen geschrieben wurde.

Um eine davon zwischen Schnittstelle und abstrakter Klasse auszuwählen, Oracle-Dokumentation page quote that:

Abstrakte Klassen sind Schnittstellen ähnlich. Sie können sie nicht instanziieren, und sie enthalten möglicherweise eine Mischung von Methoden, die mit oder ohne Implementierung deklariert wurden. Mit abstrakten Klassen können Sie jedoch Felder deklarieren, die nicht statisch und endgültig sind, und öffentliche, geschützte und private konkrete Methoden definieren. 

Bei Schnittstellen sind alle Felder automatisch public, static und final. Alle Methoden, die Sie deklarieren oder definieren (als Standardmethoden), sind public. Außerdem können Sie nur eine Klasse erweitern, unabhängig davon, ob sie abstrakt ist oder nicht, während Sie eine beliebige Anzahl von Schnittstellen implementieren können.

Weitere Informationen finden Sie in diesen verwandten Fragen: 

Schnittstelle vs. abstrakte Klasse (allgemeines OO)

Wie hätte ich den Unterschied zwischen einer Interface- und einer Abstract-Klasse erklären sollen?

Zusammenfassend: Die Waage neigt jetzt mehr zu Schnittstellen.

Gibt es neben den oben genannten Szenarien noch andere Szenarien, in denen speziell die Verwendung von abstrakten Klassen erforderlich ist (eines davon ist, dass das Vorlagenmusterentwurfsmuster nur konzeptuell darauf basiert)?

Einige Entwurfsmuster verwenden abstrakte Klassen (über Schnittstellen) neben dem Mustermuster der Vorlage. 

Schöpfungsmuster:

Abstract_factory_pattern

Strukturmuster:

Decorator_pattern

Verhaltensmuster: 

Mediator_pattern

4
Ravindra babu

Du bist nicht richtig. Es gibt viele Szenarien. Es ist einfach nicht möglich, es auf eine einzige 8-Word-Regel zu reduzieren.

3
user207421

Meiner Meinung nach besteht der grundlegende Unterschied darin, dass an interface can't contain non abstract methods while an abstract class can. Wenn also Unterklassen ein gemeinsames Verhalten aufweisen, kann dieses Verhalten in der Oberklasse implementiert und damit in die Unterklassen vererbt werden 

Ich zitierte auch das folgende Buch "Software Architecture Design ppatterns in Java"

Msgstr "In der Java - Programmiersprache gibt es keine Unterstützung für Mehrfachvererbung . Das bedeutet, dass eine Klasse nur von einer einzelnen Klasse erben kann. Daher sollte Vererbung .__ nur verwendet werden, wenn dies absolut notwendig ist. .denoting des allgemeinen Verhaltens sollte in Form einer Java-Schnittstelle deklariert werden, die von verschiedenen Implementierungsklassen implementiert werden soll. Schnittstellen unterliegen jedoch der Einschränkung, dass sie keine Implementierungen von Methoden bereitstellen können. Dies bedeutet, dass jeder Implementierer eines Interfaces muss explizit alle deklarierten Methoden in einem Interface implementieren, auch wenn einige dieser Methoden den unveränderlichen Teil der Funktionalität darstellen und in allen Implementierungsklassen genau dieselbe Implementierung haben. Dies führt zu redundantem Code Das folgende Beispiel zeigt: __. wie das Abstract-Parent-Class-Muster in solchen Fällen verwendet werden kann, ohne dass Redundante Methodenimplementierungen erforderlich ist. "

3
user2794921

Die kürzeste Antwort lautet: extend abstract class, wenn einige der von Ihnen gesuchten Funktionalitäten bereits implementiert sind.

Wenn Sie die Schnittstelle implementieren, müssen Sie die gesamte Methode implementieren. Für abstrakte Klassenanzahl von Methoden, die Sie implementieren müssen, kann es jedoch weniger sein. 

In Vorlagenentwurfsmuster Es muss ein Verhalten definiert sein. Dieses Verhalten hängt von anderen Methoden ab, die abstrakt sind. Indem Sie eine Unterklasse erstellen und diese Methoden definieren, definieren Sie tatsächlich das Hauptverhalten. Das zugrunde liegende Verhalten kann sich nicht in einer Schnittstelle befinden, da Schnittstelle nichts definiert, sondern nur deklariert. Ein Vorlagenentwurfsmuster wird also immer mit einer abstrakten Klasse geliefert. Wenn Sie den Fluss des Verhaltens beibehalten möchten, müssen Sie die abstrakte Klasse erweitern, das Hauptverhalten jedoch nicht überschreiben.

3
Shiplu Mokaddim

Abstrakte Klassen unterscheiden sich in zwei wichtigen Aspekten von Schnittstellen

  • sie bieten eine Standardimplementierung für ausgewählte Methoden (die von Ihrer Antwort abgedeckt wird).
  • abstrakte Klassen können Status (Instanzvariablen) haben. In dieser Situation möchten Sie sie anstelle von Schnittstellen verwenden
2

Hier gibt es viele großartige Antworten, aber ich finde es oft, BEIDE Schnittstellen und abstrakte Klassen zu verwenden, die beste Route. Betrachten Sie dieses erfundene Beispiel:

Sie sind Softwareentwickler bei einer Investmentbank und müssen ein System aufbauen, das Aufträge an einen Markt stellt. Ihre Benutzeroberfläche erfasst die allgemeinste Vorstellung davon, was ein Handelssystem tut,

1) Trading system places orders
2) Trading system receives acknowledgements

und kann in einer Schnittstelle erfasst werden, ITradeSystem 

public interface ITradeSystem{

     public void placeOrder(IOrder order);
     public void ackOrder(IOrder order);

}

Jetzt können Ingenieure, die am Sales Desk und in anderen Geschäftsbereichen arbeiten, mit Ihrem System interface anfangen, um ihren bestehenden Apps die Funktion zur Auftragserteilung hinzuzufügen. Und du hast noch nicht angefangen zu bauen! Das ist die Stärke von Schnittstellen.

Sie bauen also das System für stock -Händler auf. Sie haben gehört, dass Ihr System eine Funktion hat, um günstige Aktien zu finden, und sind sehr daran interessiert, es auszuprobieren! Sie erfassen dieses Verhalten in einer Methode mit dem Namen findGoodDeals(), erkennen jedoch auch, dass bei der Verbindung zu den Märkten eine Menge unordentlicher Dinge involviert sind. Zum Beispiel müssen Sie eine SocketChannel öffnen,

public class StockTradeSystem implements ITradeSystem{    

    @Override 
    public void placeOrder(IOrder order);
         getMarket().place(order);

    @Override 
    public void ackOrder(IOrder order);
         System.out.println("Order received" + order);    

    private void connectToMarket();
       SocketChannel sock = Socket.open();
       sock.bind(marketAddress); 
       <LOTS MORE MESSY CODE>
    }

    public void findGoodDeals();
       deals = <apply magic wizardry>
       System.out.println("The best stocks to buy are: " + deals);
    }

Die konkreten Implementierungen werden viele dieser chaotischen Methoden wie connectToMarket() haben, aber findGoodDeals() ist alles, was die Trader eigentlich interessieren.

Hier kommen abstrakte Klassen ins Spiel. Ihr Chef informiert Sie, dass Devisenhändler auch Ihr System verwenden möchten. Wenn Sie sich die Devisenmärkte anschauen, sehen Sie, dass die Sanitäranlagen nahezu identisch mit den Aktienmärkten sind. Tatsächlich kann connectToMarket() wörtlich wiederverwendet werden, um eine Verbindung zu Devisenmärkten herzustellen. In der Währungswelt ist findGoodDeals() jedoch ein anderes Konzept. Bevor Sie also die Codebasis an das Fremdwährungskind über den Ozean weitergeben, refactorieren Sie zunächst eine abstract-Klasse und lassen findGoodDeals() nicht implementiert

public abstract class ABCTradeSystem implements ITradeSystem{    

    public abstract void findGoodDeals();

    @Override 
    public void placeOrder(IOrder order);
         getMarket().place(order);

    @Override 
    public void ackOrder(IOrder order);
         System.out.println("Order received" + order);    

    private void connectToMarket();
       SocketChannel sock = Socket.open();
       sock.bind(marketAddress); 
       <LOTS MORE MESSY CODE>
    }

Ihr Aktienhandelssystem implementiert findGoodDeals() wie bereits definiert,

public class StockTradeSystem extends ABCTradeSystem{    

    public void findGoodDeals();
       deals = <apply magic wizardry>
       System.out.println("The best stocks to buy are: " + deals);
    }

aber jetzt kann das FX-Whizz Kid sein System aufbauen, indem es einfach eine Implementierung von findGoodDeals() für Währungen bereitstellt. Sie muss keine Socketverbindungen oder auch die Schnittstellenmethoden neu implementieren!

public class CurrencyTradeSystem extends ABCTradeSystem{    

    public void findGoodDeals();
       ccys = <Genius stuff to find undervalued currencies>
       System.out.println("The best FX spot rates are: " + ccys);
    }

Die Programmierung für eine Schnittstelle ist leistungsfähig, aber ähnliche Anwendungen implementieren Methoden auf nahezu identische Weise neu. Durch die Verwendung einer abstrakten Klasse werden Neuimplementierungen vermieden, während die Leistungsfähigkeit der Schnittstelle erhalten bleibt. 

Hinweis: Man wundert sich vielleicht, warum findGreatDeals() nicht Teil der Benutzeroberfläche ist. Denken Sie daran, dass die Schnittstelle die allgemeinsten Komponenten eines Handelssystems definiert. Ein anderer Ingenieur kann ein vollständig unterschiedliches Handelssystem entwickeln, bei dem es ihm nicht wichtig ist, gute Angebote zu finden. Die Benutzeroberfläche garantiert, dass der Sales Desk auch eine Schnittstelle zu ihrem System herstellen kann. Daher sollte die Benutzeroberfläche nicht mit Anwendungskonzepten wie "Schnäppchen" verwickelt werden.

2
Adam Hughes

Dies ist eine gute Frage. Die beiden von ihnen sind sich nicht ähnlich, können aber aus demselben Grund verwendet werden, beispielsweise eine Neuschreibung. Beim Erstellen ist es am besten, Interface zu verwenden. Wenn es auf den Unterricht ankommt, ist es gut für das Debuggen. 

1
sharonda walker

Das ist mein Verständnis, hoffe das hilft

Abstrakte Klassen:

  1. Kann über vererbte Member-Variablen verfügen (kann nicht in Schnittstellen ausgeführt werden)
  2. Kann Konstruktoren haben (Schnittstellen können nicht)
  3. Seine Methoden können eine beliebige Sichtbarkeit haben (dh private, protected usw. - wobei alle Schnittstellenmethoden öffentlich sind)
  4. Kann definierte Methoden haben (Methoden mit einer Implementierung)

Schnittstellen:

  1. Kann Variablen haben, aber sie sind alle öffentliche statische Endvariablen
    • konstante Werte, die sich niemals mit einem statischen Bereich ändern
    • nicht statische Variablen erfordern eine Instanz, und Sie können keine Schnittstelle instanziieren
  2. Alle Methoden sind abstrakt (kein Code in abstrakten Methoden)
    • der gesamte Code muss tatsächlich in der Klasse geschrieben werden, die die jeweilige Schnittstelle implementiert
0
zozep

Abstract classes should be extended when you want to some common behavior to get extended. Die abstrakte Superklasse hat das gemeinsame Verhalten und definiert abstrakte Methoden/spezifische Verhaltensweisen, die von Unterklassen implementiert werden sollen.

Interfaces allows you to change the implementation anytime allowing the interface to be intact.

0
Ramesh PVK

Verwendung von Abstract und Interface:

Einer hat "Is-A-Beziehung" und ein anderer hat "Has-A-Beziehung"

Die Standardeigenschaften wurden abstrakt eingestellt und zusätzliche Eigenschaften können über die Schnittstelle ausgedrückt werden.

Beispiel: -> In den Menschen haben wir einige Standardeigenschaften, die essen, schlafen usw., aber wenn jemand andere lehrplanmäßige Aktivitäten wie Schwimmen, Spielen usw. hat, könnten diese durch Interface ausgedrückt werden.

0
user7439667

Unterschied zwischen abstrakter Klasse und Schnittstelle

Abstrakte Klasse

  • Abstrakte Klassen können abstrakte und nicht abstrakte Methoden haben
  • die abstrakte Klasse kann nicht endgültige Variablen enthalten
  • Abstrakte Klassen können endgültige, nicht endgültige, statische und nicht statische Variablen haben
  • Eine abstrakte Klasse kann die Implementierung einer Schnittstelle bereitstellen
  • Abstrakte Klasse kann mit dem Schlüsselwort "extend" erweitert werden
  • Eine abstrakte Klasse kann eine andere Java Klasse erweitern und mehrere Java Schnittstellen implementieren
  • Eine abstrakte Klasse Java kann Klassenmitglieder wie private, protected usw. Haben

Schnittstellen

  • Die Schnittstelle kann nur abstrakte Methoden haben
  • In einer Java - Schnittstelle deklarierte Variablen sind standardmäßig final
  • Die Schnittstelle hat nur statische und endgültige Variablen
  • Die Schnittstelle kann die Implementierung einer abstrakten Klasse nicht bereitstellen
  • Eine Java -Schnittstelle kann mit dem Schlüsselwort "implements" implementiert werden.
  • Eine Schnittstelle kann nur eine andere Java Schnittstelle erweitern
  • Mitglieder einer Java - Schnittstelle sind standardmäßig öffentlich
0