In einem meiner Interviews wurde ich gebeten, den Unterschied zwischen einem Interface und einem Abstract class zu erklären.
Hier ist meine Antwort:
Methoden einer Java -Schnittstelle sind implizit abstrakt und können nicht implementiert werden. Eine Java abstrakte Klasse kann Instanzmethoden haben, die ein Standardverhalten implementieren.
In einer Java -Schnittstelle deklarierte Variablen sind standardmäßig final. Eine abstrakte Klasse kann nicht endgültige Variablen enthalten.
Mitglieder einer Java -Schnittstelle sind standardmäßig öffentlich. Eine Java abstrakte Klasse kann die üblichen Varianten von Klassenmitgliedern wie privat, geschützt usw. haben.
Eine Java -Schnittstelle sollte mit dem Schlüsselwort "implements" implementiert werden. Eine Java abstrakte Klasse sollte mit dem Schlüsselwort "extend" erweitert werden.
Eine Schnittstelle kann nur eine andere Java Schnittstelle erweitern, eine abstrakte Klasse kann eine andere Java Klasse erweitern und mehrere Java Schnittstellen implementieren.
Eine Klasse Java kann mehrere Schnittstellen implementieren, aber nur eine abstrakte Klasse erweitern.
Der Interviewer war jedoch nicht zufrieden und sagte mir, dass diese Beschreibung " Buchwissen " darstellt.
Er bat mich um eine praktischere Antwort und erklärte , wann ich eine abstrakte Klasse über eine Schnittstelle wählen würde, unter Verwendung praktischer Beispiele .
Was habe ich falsch gemacht?
Ich werde Ihnen zuerst ein Beispiel geben:
public interface LoginAuth{
public String encryptPassword(String pass);
public void checkDBforUser();
}
Angenommen, Ihre Anwendung enthält 3 Datenbanken. Dann muss jede Implementierung für diese Datenbank die obigen 2 Methoden definieren:
public class DBMySQL implements LoginAuth{
// Needs to implement both methods
}
public class DBOracle implements LoginAuth{
// Needs to implement both methods
}
public class DBAbc implements LoginAuth{
// Needs to implement both methods
}
Aber was ist, wenn encryptPassword () nicht datenbankabhängig ist und für jede Klasse gleich ist? Dann wäre das Obige kein guter Ansatz.
Betrachten Sie stattdessen diesen Ansatz:
public abstract class LoginAuth{
public String encryptPassword(String pass){
// Implement the same default behavior here
// that is shared by all subclasses.
}
// Each subclass needs to provide their own implementation of this only:
public abstract void checkDBforUser();
}
Jetzt müssen wir in jeder untergeordneten Klasse nur noch eine Methode implementieren - die Methode, die datenbankabhängig ist.
Ich habe mein Bestes versucht und hoffe, dies wird Ihre Zweifel klären.
Nichts ist perfekt auf dieser Welt. Sie haben vielleicht eher einen praktischen Ansatz erwartet.
Nach Ihrer Erklärung können Sie diese Zeilen jedoch mit einem etwas anderen Ansatz hinzufügen.
Schnittstellen sind Regeln (Regeln, weil Sie ihnen eine Implementierung geben müssen, die Sie nicht ignorieren oder vermeiden können, damit sie wie Regeln auferlegt werden), die als gemeinsames Dokument für das Verständnis zwischen verschiedenen Teams in der Softwareentwicklung fungieren.
Schnittstellen geben die Idee, was zu tun ist, aber nicht, wie es getan wird. Die Implementierung hängt also vollständig vom Entwickler ab, indem die angegebenen Regeln befolgt werden (dh die Signatur der Methoden).
Abstrakte Klassen können abstrakte Deklarationen, konkrete Implementierungen oder beides enthalten.
Abstrakte Deklarationen sind wie Regeln, die befolgt werden müssen, und konkrete Implementierungen sind wie Richtlinien (Sie können sie unverändert verwenden oder ignorieren, indem Sie sie überschreiben und ihre eigene Implementierung zuweisen).
Darüber hinaus werden die Methoden mit derselben Signatur, die das Verhalten in verschiedenen Kontexten ändern können, als Schnittstellendeklarationen als Regeln bereitgestellt, um sie in verschiedenen Kontexten entsprechend zu implementieren.
Edit: Java 8 erleichtert das Definieren von Standardmethoden und statischen Methoden in der Schnittstelle.
public interface SomeInterfaceOne {
void usualAbstractMethod(String inputString);
default void defaultMethod(String inputString){
System.out.println("Inside SomeInterfaceOne defaultMethod::"+inputString);
}
}
Wenn eine Klasse SomeInterface implementiert, ist es nicht zwingend erforderlich, eine Implementierung für Standardschnittstellenmethoden bereitzustellen.
Wenn wir eine andere Schnittstelle mit folgenden Methoden haben:
public interface SomeInterfaceTwo {
void usualAbstractMethod(String inputString);
default void defaultMethod(String inputString){
System.out.println("Inside SomeInterfaceTwo defaultMethod::"+inputString);
}
}
In Java ist es nicht möglich, mehrere Klassen zu erweitern, da dies zum "Diamond-Problem" führt, bei dem der Compiler nicht entscheiden kann, welche Methode der Superklasse verwendet werden soll. Bei den Standardmethoden tritt das Diamantproblem auch bei Schnittstellen auf. Denn wenn eine Klasse beide implementiert
SomeInterfaceOne and SomeInterfaceTwo
wenn die allgemeine Standardmethode nicht implementiert wird, kann der Compiler nicht entscheiden, welche Methode ausgewählt werden soll. Um dieses Problem zu vermeiden, ist es in Java 8 obligatorisch, gemeinsame Standardmethoden für verschiedene Schnittstellen zu implementieren. Wenn eine Klasse beide oben genannten Schnittstellen implementiert, muss sie die Implementierung für die defaultMethod () -Methode bereitstellen, da der Compiler sonst einen Fehler bei der Kompilierung auslöst.
Sie haben die praktischen Unterschiede in der Verwendung und Implementierung gut zusammengefasst, aber nichts über den Unterschied in der Bedeutung gesagt.
Eine Schnittstelle beschreibt das Verhalten einer implementierenden Klasse. Die implementierende Klasse stellt sicher, dass diese Methoden verwendet werden können. Es ist im Grunde ein Vertrag oder ein Versprechen, das die Klasse machen muss.
Eine abstrakte Klasse ist eine Basis für verschiedene Unterklassen, die ein gemeinsames Verhalten aufweisen und nicht wiederholt erstellt werden müssen. Unterklassen müssen das Verhalten vervollständigen und die Option haben, vordefiniertes Verhalten zu überschreiben (solange es nicht als final
oder private
definiert ist).
Sie finden gute Beispiele im Paket Java.util
, das Schnittstellen wie List
und abstrakte Klassen wie AbstractList
enthält, die die Schnittstelle bereits implementieren. Die offizielle Dokumentation beschreibt die AbstractList
wie folgt:
Diese Klasse bietet eine grundlegende Implementierung der List-Schnittstelle, um den Aufwand für die Implementierung dieser Schnittstelle zu minimieren, die durch einen Datenspeicher mit wahlfreiem Zugriff (z. B. ein Array) unterstützt wird.
Eine Schnittstelle besteht aus Singleton-Variablen (public static final) und öffentlichen abstrakten Methoden. Normalerweise bevorzugen wir die Verwendung einer Schnittstelle in Echtzeit, wenn wir wissen was zu tun ist, aber nicht wissen, wie es zu tun ist .
Dieses Konzept kann am Beispiel besser verstanden werden:
Betrachten Sie eine Zahlungsklasse. Die Zahlung kann auf verschiedene Arten erfolgen, z. B. über Paypal, Kreditkarte usw. Normalerweise verwenden wir also Payment als Schnittstelle, die eine makePayment()
-Methode enthält, und CreditCard und Paypal sind die beiden Implementierungsklassen.
public interface Payment
{
void makePayment();//by default it is a abstract method
}
public class Paypal implements Payment
{
public void makePayment()
{
//some logic for Paypal payment
//e.g. Paypal uses username and password for payment
}
}
public class CreditCard implements Payment
{
public void makePayment()
{
//some logic for CreditCard payment
//e.g. CreditCard uses card number, date of expiry etc...
}
}
Im obigen Beispiel sind CreditCard und Paypal zwei Implementierungsklassen/-strategien. Eine Schnittstelle ermöglicht uns auch das Konzept der Mehrfachvererbung in Java, das von einer abstrakten Klasse nicht ausgeführt werden kann.
Wir wählen eine abstrakte Klasse, wenn es einige Funktionen gibt, für die wir wissen, was zu tun ist, und andere Funktionen, für die wir wissen, wie sie auszuführen sind.
Betrachten Sie das folgende Beispiel:
public abstract class Burger
{
public void packing()
{
//some logic for packing a burger
}
public abstract void price(); //price is different for different categories of burgers
}
public class VegBerger extends Burger
{
public void price()
{
//set price for a veg burger.
}
}
public class NonVegBerger extends Burger
{
public void price()
{
//set price for a non-veg burger.
}
}
Wenn wir einer gegebenen abstrakten Klasse in Zukunft Methoden (konkret/abstrakt) hinzufügen, muss der Code der Implementierungsklasse nicht geändert werden. Wenn wir jedoch in Zukunft Methoden in eine Schnittstelle einfügen, müssen wir allen Klassen, die diese Schnittstelle implementiert haben, Implementierungen hinzufügen. Andernfalls treten Fehler bei der Kompilierung auf.
Es gibt noch andere Unterschiede, aber es handelt sich hierbei möglicherweise um größere, die von Ihrem Interviewer erwartet wurden. Hoffentlich war das hilfreich.
Java 8-Schnittstellenänderungen umfassen statische Methoden und Standardmethoden in Schnittstellen. Vor Java 8 konnten wir nur Methodendeklarationen in den Interfaces haben. Ab Java 8 können wir jedoch Standardmethoden und statische Methoden in den Schnittstellen haben.
Nach der Einführung der Standardmethode scheinen Schnittstellen und abstrakte Klassen identisch zu sein. In Java 8 sind sie jedoch immer noch ein anderes Konzept.
Abstrakte Klasse kann Konstruktor definieren. Sie sind strukturierter und können einen damit verbundenen Zustand haben. Im Gegensatz dazu kann die Standardmethode nur implementiert werden, indem andere Schnittstellenmethoden aufgerufen werden, ohne dass auf den Status einer bestimmten Implementierung verwiesen wird. Daher hängt sowohl die Verwendung für unterschiedliche Zwecke als auch die Auswahl zwischen zwei wirklich vom Szenariokontext ab.
Abstrakte Klassen sind für skelettartige (d. H. Teilweise) Implementierungen von Schnittstellen gültig, sollten jedoch nicht ohne eine passende Schnittstelle existieren.
Können Standardmethoden dies auch beseitigen, wenn abstrakte Klassen effektiv auf geringe Sichtbarkeit reduziert werden? Beschlossen: Nein! Für die Implementierung von Schnittstellen sind fast immer einige oder alle Tools zur Klassenerstellung erforderlich, denen Standardmethoden fehlen. Und wenn einige Schnittstellen dies nicht tun, handelt es sich eindeutig um einen Sonderfall, der Sie nicht in die Irre führen sollte.
Java 8 führt die neue Funktion " Standardmethode " oder "Defender-Methode" ein, mit der Entwickler den Schnittstellen neue Methoden hinzufügen können, ohne die vorhandene Implementierung dieser Schnittstelle zu beeinträchtigen. Sie bietet Flexibilität, damit die Schnittstelle eine Implementierung definieren kann, die als Standard verwendet wird, wenn eine konkrete Klasse keine Implementierung für diese Methode bereitstellt.
Betrachten wir ein kleines Beispiel, um zu verstehen, wie es funktioniert:
public interface OldInterface {
public void existingMethod();
default public void newDefaultMethod() {
System.out.println("New default method"
+ " is added in interface");
}
}
Die folgende Klasse wird erfolgreich in Java JDK 8 kompiliert.
public class OldInterfaceImpl implements OldInterface {
public void existingMethod() {
// existing implementation is here…
}
}
Wenn Sie eine Instanz von OldInterfaceImpl erstellen:
OldInterfaceImpl obj = new OldInterfaceImpl ();
// print “New default method add in interface”
obj.newDefaultMethod();
Standardmethoden sind niemals endgültig, können nicht synchronisiert werden und können die Methoden von Object nicht überschreiben. Sie sind immer öffentlich, was die Möglichkeit, kurze und wiederverwendbare Methoden zu schreiben, stark einschränkt.
Standardmethoden können einer Schnittstelle bereitgestellt werden, ohne dass dies Auswirkungen auf die Implementierung von Klassen hat, da sie eine Implementierung enthält. Wenn jede hinzugefügte Methode in einem Interface mit Implementierung definiert ist, ist keine implementierende Klasse betroffen. Eine implementierende Klasse kann die von der Schnittstelle bereitgestellte Standardimplementierung überschreiben.
Standardmethoden ermöglichen das Hinzufügen neuer Funktionen zu vorhandenen Schnittstellen, ohne die ältere Implementierung dieser Schnittstellen zu beeinträchtigen.
Wenn wir eine Schnittstelle erweitern, die eine Standardmethode enthält, können wir Folgendes ausführen:
Für Java 8 wurden die JDK-Sammlungen erweitert und forEach-Methoden zur gesamten Sammlung hinzugefügt (die in Verbindung mit Lambdas funktionieren). Auf herkömmliche Weise sieht der Code wie folgt aus:
public interface Iterable<T> {
public void forEach(Consumer<? super T> consumer);
}
Da dies zu jeder implementierenden Klasse mit Kompilierungsfehlern führt, wird daher eine Standardmethode mit einer erforderlichen Implementierung hinzugefügt, damit die vorhandene Implementierung nicht geändert wird.
Die Iterable-Schnittstelle mit der Standardmethode ist unten aufgeführt.
public interface Iterable<T> {
public default void forEach(Consumer
<? super T> consumer) {
for (T t : this) {
consumer.accept(t);
}
}
}
Der gleiche Mechanismus wurde verwendet, um Stream in die JDK-Schnittstelle einzufügen, ohne die implementierenden Klassen zu unterbrechen.
Da Java Class mehrere Interfaces implementieren kann und jedes Interface eine Standardmethode mit derselben Methodensignatur definieren kann, können die geerbten Methoden miteinander in Konflikt stehen.
Betrachten Sie das folgende Beispiel:
public interface InterfaceA {
default void defaultMethod(){
System.out.println("Interface A default method");
}
}
public interface InterfaceB {
default void defaultMethod(){
System.out.println("Interface B default method");
}
}
public class Impl implements InterfaceA, InterfaceB {
}
Der obige Code kann mit dem folgenden Fehler nicht kompiliert werden:
Java: Klasse Impl erbt nicht verwandte Standardwerte für defaultMethod () von den Typen InterfaceA und InterfaceB
Um diese Klasse zu reparieren, müssen wir eine Standardmethodenimplementierung bereitstellen:
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
}
}
Wenn wir die Standardimplementierung aufrufen möchten, die von einem der Super-Interfaces bereitgestellt wird, und nicht von unserer eigenen Implementierung, können wir dies wie folgt tun:
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
// existing code here..
InterfaceA.super.defaultMethod();
}
}
Als Teil unserer neuen Methode können wir eine Standardimplementierung oder beides auswählen.
Statische Methode der Java-Schnittstelle, Codebeispiel, statische Methode vs. Standardmethode
Die statische Methode der Java-Schnittstelle ähnelt der Standardmethode, außer dass wir sie in den Implementierungsklassen nicht überschreiben können. Diese Funktion hilft uns, unerwünschte Ergebnisse zu vermeiden, die bei einer schlechten Implementierung in Implementierungsklassen auftreten können. Lassen Sie uns dies anhand eines einfachen Beispiels untersuchen.
public interface MyData {
default void print(String str) {
if (!isNull(str))
System.out.println("MyData Print::" + str);
}
static boolean isNull(String str) {
System.out.println("Interface Null Check");
return str == null ? true : "".equals(str) ? true : false;
}
}
Sehen wir uns nun eine Implementierungsklasse an, die die isNull () -Methode mit einer schlechten Implementierung hat.
public class MyDataImpl implements MyData {
public boolean isNull(String str) {
System.out.println("Impl Null Check");
return str == null ? true : false;
}
public static void main(String args[]){
MyDataImpl obj = new MyDataImpl();
obj.print("");
obj.isNull("abc");
}
}
Beachten Sie, dass isNull (String str) eine einfache Klassenmethode ist und die Schnittstellenmethode nicht überschreibt. Wenn wir beispielsweise die Annotation @Override zur Methode isNull () hinzufügen, führt dies zu einem Compilerfehler.
Wenn wir jetzt die Anwendung ausführen, erhalten wir folgende Ausgabe.
Interface Null Check
Impl Null Check
Wenn wir die Schnittstellenmethode von statisch auf Standard setzen, erhalten wir folgende Ausgabe.
Impl Null Check
MyData Print ::
Impl Null Check
Die statische Java-Schnittstellenmethode ist nur für Schnittstellenmethoden sichtbar. Wenn Sie die isNull () -Methode aus der MyDataImpl-Klasse entfernen, können Sie sie nicht für das MyDataImpl-Objekt verwenden. Wie bei anderen statischen Methoden können wir auch bei statischen Methoden der Benutzeroberfläche Klassennamen verwenden. Eine gültige Anweisung lautet beispielsweise:
boolean result = MyData.isNull("abc");
Bevor ich den Beitrag abschließe, möchte ich eine kurze Einführung in funktionale Schnittstellen geben. Eine Schnittstelle mit genau einer abstrakten Methode wird als Functional Interface bezeichnet.
Eine neue Annotation @FunctionalInterface
wurde eingeführt, um eine Schnittstelle als funktionale Schnittstelle zu kennzeichnen. @FunctionalInterface
Annotation ist eine Funktion, mit der das versehentliche Hinzufügen abstrakter Methoden zu den funktionalen Schnittstellen verhindert wird. Es ist optional, aber eine gute Praxis, es zu verwenden.
Funktionale Interfaces werden von Java 8 lange erwartet und nachgefragt, da wir damit Lambda-Ausdrücke verwenden können, um sie zu instanziieren. Ein neues Paket Java.util.function mit einer Reihe von Funktionsschnittstellen wurde hinzugefügt, um Zieltypen für Lambda-Ausdrücke und Methodenreferenzen bereitzustellen. Wir werden uns in zukünftigen Beiträgen mit funktionalen Schnittstellen und Lambda-Ausdrücken befassen.
Alle Ihre Aussagen mit Ausnahme Ihrer ersten Aussage (nach der Version Java 8) sind gültig:
Methoden einer Java -Schnittstelle sind implizit abstrakt und können nicht implementiert werden
Aus der Dokumentation Seite :
Eine Schnittstelle ist ein Referenztyp, der einer Klasse ähnlich ist und nur Konstanten, Methodensignaturen, Standardmethoden, statische Methoden und verschachtelte Typen enthalten kann.
Methodenkörper existieren nur für Standardmethoden und statische Methoden.
Standardmethoden:
Eine Schnittstelle kann Standardmethoden haben, unterscheidet sich jedoch von abstrakten Methoden in abstrakten Klassen.
Mit Standardmethoden können Sie den Schnittstellen Ihrer Bibliotheken neue Funktionen hinzufügen und die Binärkompatibilität mit Code sicherstellen, der für ältere Versionen dieser Schnittstellen geschrieben wurde.
Wenn Sie eine Schnittstelle erweitern, die eine Standardmethode enthält, können Sie Folgendes tun:
abstract
wird.Statische Methoden:
Zusätzlich zu Standardmethoden können Sie statische Methoden in Schnittstellen definieren. (Eine statische Methode ist eine Methode, die der Klasse zugeordnet ist, in der sie definiert ist, und nicht einem Objekt. Jede Instanz der Klasse verwendet ihre statischen Methoden gemeinsam.)
Dies erleichtert Ihnen das Organisieren von Hilfsmethoden in Ihren Bibliotheken.
Beispielcode von der Dokumentationsseite über interface
mit static
und default
Methoden.
import Java.time.*;
public interface TimeClient {
void setTime(int hour, int minute, int second);
void setDate(int day, int month, int year);
void setDateAndTime(int day, int month, int year,
int hour, int minute, int second);
LocalDateTime getLocalDateTime();
static ZoneId getZoneId (String zoneString) {
try {
return ZoneId.of(zoneString);
} catch (DateTimeException e) {
System.err.println("Invalid time zone: " + zoneString +
"; using default time zone instead.");
return ZoneId.systemDefault();
}
}
default ZonedDateTime getZonedDateTime(String zoneString) {
return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
}
}
Verwenden Sie die folgenden Richtlinien, um auszuwählen, ob Sie eine Schnittstelle oder eine abstrakte Klasse verwenden möchten.
Schnittstelle:
Abstrakte Klasse:
Teilen Sie Code zwischen mehreren eng verwandten Klassen. Es stellt eine Beziehung her.
Gemeinsamen Status unter verwandten Klassen teilen (Status kann in konkreten Klassen geändert werden)
Zusammenhängende Posts:
Schnittstelle gegen abstrakte Klasse (allgemeines OO)
Implementiert vs erweitert: Wann verwenden? Was ist der Unterschied?
Wenn Sie diese Beispiele durchgehen, können Sie das verstehen
Nicht verwandte Klassen können Funktionen über die Schnittstelle haben, aber verwandte Klassen ändern das Verhalten durch Erweiterung von Basisklassen.
Ihre Erklärung sieht anständig aus, aber könnte es sein, dass Sie alles aus einem Lehrbuch gelesen haben? : - /
Was mich mehr stört, ist, wie solide war Ihr Beispiel? Haben Sie sich die Mühe gemacht, fast alle Unterschiede zwischen abstrakt und Schnittstellen aufzunehmen ?
Persönlich würde ich diesen Link vorschlagen: http://mindprod.com/jgloss/interfacevsabstract.html#TABLE
für eine vollständige Liste der Unterschiede ..
Hoffe, es hilft dir und allen anderen Lesern bei ihren zukünftigen Interviews
Viele Nachwuchsentwickler machen den Fehler, Schnittstellen, abstrakte und konkrete Klassen als geringfügige Variationen derselben Sache zu betrachten, und wählen aus rein technischen Gründen eine aus: Benötige ich Mehrfachvererbung? Benötige ich einen Platz, um gängige Methoden anzuwenden? Muss ich mich mit etwas anderem als nur einer konkreten Klasse beschäftigen? Das ist falsch und in diesen Fragen ist das Hauptproblem verborgen: "I". Wenn Sie selbst Code schreiben, denken Sie selten an andere gegenwärtige oder zukünftige Entwickler, die an oder mit Ihrem Code arbeiten.
Schnittstellen und abstrakte Klassen haben völlig unterschiedliche Bedeutungen und Zwecke, obwohl sie aus technischer Sicht offensichtlich ähnlich sind.
Eine Schnittstelle definiert einen Vertrag die eine Implementierung für Sie erfüllen wird .
Eine abstrakte Klasse liefert ein Standardverhalten die Ihre Implementierung wiederverwenden kann.
Diese beiden obigen Punkte sind das, wonach ich beim Vorstellungsgespräch suche, und sie sind eine ausreichend kompakte Zusammenfassung. Lesen Sie weiter für weitere Details.
Anders ausgedrückt: Eine konkrete Klasse erledigt die eigentliche Arbeit auf ganz bestimmte Weise. Beispielsweise verwendet ein ArrayList
einen zusammenhängenden Speicherbereich, um eine Liste von Objekten auf kompakte Weise zu speichern. Dies bietet schnellen wahlfreien Zugriff, Iteration und direkte Änderungen, ist jedoch bei Einfügungen, Löschungen und gelegentlich sogar schrecklich Ergänzungen; Ein LinkedList
verwendet doppelt verknüpfte Knoten, um eine Liste von Objekten zu speichern, die stattdessen eine schnelle Iteration, direkte Änderungen und das Einfügen/Löschen/Hinzufügen bietet, aber beim wahllosen Zugriff furchtbar ist. Diese beiden Arten von Listen sind für unterschiedliche Anwendungsfälle optimiert, und es ist sehr wichtig, wie Sie sie verwenden. Wenn Sie versuchen, die Leistung aus einer Liste herauszuholen, mit der Sie intensiv interagieren, und wenn Sie die Art der Liste bestimmen, sollten Sie sorgfältig auswählen, welche Sie instanziieren.
Andererseits ist es Benutzern auf hoher Ebene einer Liste egal, wie sie tatsächlich implementiert wird, und sie sollten von diesen Details isoliert sein. Stellen wir uns vor, dass Java die List
-Schnittstelle nicht verfügbar gemacht hat, sondern nur eine konkrete List
-Klasse hat, die genau das ist, was LinkedList
gerade ist. Alle Java - Entwickler hätten ihren Code an die Implementierungsdetails angepasst: Vermeiden Sie zufälligen Zugriff, fügen Sie einen Cache hinzu, um den Zugriff zu beschleunigen, oder implementieren Sie ArrayList
einfach neu, obwohl dies nicht mit allen kompatibel wäre anderer Code, der tatsächlich nur mit List
funktioniert. Das wäre schrecklich ... Aber stellen Sie sich jetzt vor, dass die Java - Master tatsächlich erkennen, dass eine verknüpfte Liste für die meisten tatsächlichen Anwendungsfälle schrecklich ist, und beschlossen, für ihre einzige Klasse List
auf eine Array-Liste umzuschalten verfügbar. Dies würde die Leistung jedes Java Programms auf der Welt beeinträchtigen, und die Leute wären darüber nicht glücklich. Der Hauptschuldige ist, dass Implementierungsdetails verfügbar waren, und die Entwickler gingen davon aus, dass diese Details ein dauerhafter Vertrag sind, auf den sie sich verlassen können. Aus diesem Grund ist es wichtig, Implementierungsdetails auszublenden und nur einen abstrakten Vertrag zu definieren. Dies ist der Zweck einer Schnittstelle: Definieren Sie, welche Art von Eingabe eine Methode akzeptiert und welche Art von Ausgabe erwartet, ohne all die Eingeweide aufzudecken, die Programmierer dazu verleiten würden, ihren Code an die internen Details anzupassen, die sich bei zukünftigen Aktualisierungen ändern könnten .
Eine abstrakte Klasse befindet sich in der Mitte zwischen Interfaces und konkreten Klassen. Es soll Implementierungen dabei helfen, gemeinsamen oder langweiligen Code zu verwenden. Beispielsweise bietet AbstractCollection
grundlegende Implementierungen für isEmpty
basierend auf der Größe 0, contains
als Iteration und Vergleich, addAll
als Wiederholung add
und so weiter. So können sich die Implementierungen auf die entscheidenden Teile konzentrieren, die sie voneinander unterscheiden: das Speichern und Abrufen von Daten.
Schnittstellen sind kohäsionsarm Gateways zwischen verschiedenen Codeteilen. Sie ermöglichen es Bibliotheken zu existieren und sich zu entwickeln, ohne jeden Bibliotheksbenutzer zu unterbrechen, wenn sich intern etwas ändert. Es heißt Application Programming Interface, nicht Application Programming Classes. In kleinerem Maßstab ermöglichen sie auch mehreren Entwicklern die erfolgreiche Zusammenarbeit in großen Projekten, indem sie verschiedene Module durch gut dokumentierte Schnittstellen trennen.
Abstrakte Klassen haben eine hohe Kohäsion Helfer, die bei der Implementierung einer Schnittstelle verwendet werden sollen, vorausgesetzt, dass ein gewisser Grad an Implementierungsdetails vorliegt. Alternativ werden abstrakte Klassen zum Definieren von SPIs (Service Provider Interfaces) verwendet.
Der Unterschied zwischen einer API und einem SPI ist subtil, aber wichtig: Bei einer API liegt der Fokus auf who ses und bei einem SPI liegt der Fokus auf who implementiert it.
Das Hinzufügen von Methoden zu einer API ist einfach. Alle vorhandenen Benutzer der API werden weiterhin kompiliert. Das Hinzufügen von Methoden zu einem SPI ist schwierig, da jeder Dienstanbieter (konkrete Implementierung) die neuen Methoden implementieren muss. Wenn zur Definition eines SPI Schnittstellen verwendet werden, muss ein Anbieter bei jeder Änderung des Vertrags SPI eine neue Version freigeben. Wenn stattdessen abstrakte Klassen verwendet werden, können neue Methoden entweder als vorhandene abstrakte Methoden oder als leere throw not implemented exception
-Stubs definiert werden, sodass zumindest eine ältere Version einer Service-Implementierung weiterhin kompiliert und ausgeführt werden kann.
Obwohl in Java 8 Standardmethoden für Schnittstellen eingeführt wurden, wodurch die Grenze zwischen Schnittstellen und abstrakten Klassen noch unschärfer wird, können Implementierungen den Code nicht wiederverwenden, sondern erleichtern das Ändern von Schnittstellen, die beide als API dienen und als SPI (oder werden fälschlicherweise zum Definieren von SPIs anstelle von abstrakten Klassen verwendet).
Die technischen Details in der Antwort des OP gelten als "Buchwissen", da dies normalerweise der in der Schule und in den meisten Technologiebüchern verwendete Ansatz zu einer Sprache ist: was eine Sache ist, nicht wie) um es in der Praxis zu verwenden, insbesondere in großen Anwendungen.
Hier ist eine Analogie: Vermutlich lautete die Frage:
Was ist besser für einen Abschlussball, ein Auto oder ein Hotelzimmer zu mieten?
Die technische Antwort klingt wie folgt:
Nun, in einem Auto kann man es früher machen, aber in einem Hotelzimmer kann man es bequemer machen. Auf der anderen Seite befindet sich das Hotelzimmer nur an einem Ort, während Sie es im Auto an mehreren Orten erledigen können. Nehmen wir an, Sie können zum Vista-Punkt gehen, um eine schöne Aussicht zu genießen, oder in einem Autokino. oder an vielen anderen Orten oder sogar an mehr als einem Ort. Das Hotelzimmer hat auch eine Dusche.
Das ist alles wahr, aber es geht völlig daneben, dass es sich um zwei völlig verschiedene Dinge handelt und beide gleichzeitig für unterschiedliche Zwecke verwendet werden können, und der Aspekt "es zu tun" ist bei keiner der beiden Optionen das Wichtigste . Der Antwort fehlt die Perspektive, sie zeigt eine unausgereifte Denkweise, während sie die wahren "Tatsachen" korrekt darstellt.
Eine Schnittstelle ist ein "Vertrag", bei dem die Klasse, die den Vertrag implementiert, verspricht, die Methoden zu implementieren. Ein Beispiel, bei dem ich anstelle einer Klasse eine Benutzeroberfläche schreiben musste, war die Aktualisierung eines Spiels von 2D auf 3D. Ich musste eine Schnittstelle erstellen, um Klassen zwischen der 2D- und der 3D-Version des Spiels zu teilen.
package adventure;
import Java.awt.*;
public interface Playable {
public void playSound(String s);
public Image loadPicture(String s);
}
Dann kann ich die Methoden basierend auf der Umgebung implementieren und diese Methoden dennoch von einem Objekt aufrufen, das nicht weiß, welche Version des Spiels geladen wird.
public class Adventure extends JFrame implements Playable
public class Dungeon3D extends SimpleApplication implements Playable
public class Main extends SimpleApplication implements AnimEventListener, ActionListener, Playable
Typischerweise kann die Welt in der Spielwelt eine abstrakte Klasse sein, die Methoden für das Spiel ausführt:
public abstract class World...
public Playable owner;
public Playable getOwner() {
return owner;
}
public void setOwner(Playable owner) {
this.owner = owner;
}
Was ist mit folgender Denkweise:
Wenn Sie also eine abstrakte Klasse Säugetiere, eine Unterklasse Mensch und eine Schnittstelle Fahren haben, dann können Sie sagen
Mein Vorschlag ist, dass der Buchwissenssatz anzeigt, dass er den semantischen Unterschied zwischen beiden hören wollte (wie andere hier bereits vorgeschlagen).
Abstrakte Klassen sind keine reine Abstraktion, sondern eine Sammlung konkreter (implementierter) und nicht implementierter Methoden. Aber Schnittstellen sind reine Abstraktion. Es gibt nur unimplementierte Methoden, keine konkreten Methoden.
Warum abstrakte Klassen?
Warum Schnittstellen?
Eine Schnittstelle ist wie eine Reihe von Genen, deren Wirkung öffentlich dokumentiert ist: Ein DNA-Test sagt mir, ob ich sie habe - und wenn ich das tue, kann ich öffentlich bekannt machen, dass ich ein "Träger" bin und ein Teil meines Verhaltens oder Zustands ihnen entsprechen wird. (Aber natürlich habe ich möglicherweise viele andere Gene, die Merkmale bieten, die außerhalb dieses Bereichs liegen.)
Eine abstrakte Klasse ist wie die tote Vorfahrin einer gleichgeschlechtlichen Spezies (*): Sie kann nicht dazu gebracht werden Das Leben aber ein lebender (dh nicht abstrakter ) Nachkomme erbt alle ihre Gene.
(*) Um diese Metapher zu erweitern, nehmen wir an, dass alle Mitglieder der Spezies dasselbe Alter haben. Das heißt, alle Vorfahren eines toten Vorfahren müssen ebenfalls tot sein - und ebenso müssen alle Nachkommen eines lebenden Vorfahren am Leben sein.
Ich mache Interviews für die Arbeit und ich würde Ihre Antwort auch ungünstig sehen (sorry, aber ich bin sehr ehrlich). Es hört sich so an, als hätten Sie über den Unterschied gelesen und eine Antwort überarbeitet, aber vielleicht haben Sie sie noch nie in der Praxis verwendet.
Eine gute Erklärung, warum Sie beide verwenden, kann weitaus besser sein als eine genaue Erklärung des Unterschieds. Die Arbeitgeber möchten, dass die Programmierer Dinge tun, die sie nicht kennen, was sich in einem Interview nur schwer demonstrieren lässt. Die Antwort, die Sie gaben, wäre gut, wenn Sie sich für einen technischen oder dokumentationsbasierten Job bewerben würden, aber nicht als Entwickler.
Viel Glück mit Interviews in der Zukunft.
Meine Antwort auf diese Frage bezieht sich eher auf die Interviewtechnik als auf das von Ihnen bereitgestellte technische Material. Vielleicht sollten Sie darüber nachdenken. https://workplace.stackexchange.com/ kann ein ausgezeichneter Ort für solche Dinge sein.
Eine Schnittstelle ist rein abstrakt. Wir haben keinen Implementierungscode in der Schnittstelle.
Die abstrakte Klasse enthält beide Methoden und ihre Implementierung.
Klicken Sie hier, um das Tutorial zu Schnittstellen und abstrakten Klassen zu sehen.
Der Hauptunterschied, den ich beobachtet habe, war, dass die abstrakte Klasse uns einige bereits implementierte allgemeine Verhaltensweisen bietet und Unterklassen nur spezifische Funktionen implementieren müssen, die ihnen entsprechen. Wobei für eine Schnittstelle nur spezifiziert wird, welche Aufgaben zu erledigen sind, und von der Schnittstelle keine Implementierungen angegeben werden. Ich kann sagen, es spezifiziert den Vertrag zwischen sich selbst und implementierten Klassen.
Sogar ich habe mich in mehreren Interviews der gleichen Frage gestellt und glaube mir, es macht deine Zeit miserabel, den Interviewer zu überzeugen. Wenn mir alle Antworten von oben inhärent sind, muss ich noch einen wichtigen Punkt hinzufügen, damit es überzeugender ist und OO von seiner besten Seite ist
Für den Fall, dass Sie nicht sind planung von Änderungen in den Regeln Wenn die Unterklasse für eine lange Zukunft befolgt werden soll, wählen Sie die Schnittstelle, da Sie sie nicht ändern können, und wenn Sie dies tun, müssen Sie die Änderungen für alle anderen Unterklassen vornehmen du denkst, sie möchten die Funktionalität wiederverwenden, einige Regeln festlegen und sie auch für Änderungen öffnen, geh in die abstrakte Klasse.
Denken Sie auf diese Weise, Sie hätten einen Verbrauchsgüter-Service verwendet oder der Welt einen Code zur Verfügung gestellt, und Sie hätten die Möglichkeit, etwas zu ändern. Nehmen Sie eine Sicherheitsüberprüfung an Finde alle gelesenen Markierungen in meiner Eclipse, die gesamte Anwendung ist ausgefallen. Um solche Alpträume zu vermeiden, verwenden Sie Abstract over Interfaces
Ich denke, das könnte den Interviewer in gewissem Maße überzeugen ... Frohe Interviews voraus.
Sie wählen Interface in Java, um das Diamond-Problem bei Mehrfachvererbung zu vermeiden.
Wenn Sie möchten, dass alle Ihre Methoden von Ihrem Client implementiert werden, entscheiden Sie sich für eine Schnittstelle. Dies bedeutet, dass Sie die gesamte Anwendung abstrakt gestalten.
Sie wählen die abstrakte Klasse, wenn Sie bereits wissen, was gemeinsam ist. Nehmen Sie zum Beispiel eine abstrakte Klasse Car
. Auf einer höheren Ebene implementieren Sie die gängigen Automethoden wie calculateRPM()
. Es ist eine gängige Methode und Sie lassen den Kunden sein eigenes Verhalten gerne umsetzencalculateMaxSpeed()
etc. Wahrscheinlich hätten Sie das anhand weniger Echtzeitbeispiele erklärt, die Sie in Ihrem täglichen Job erlebt haben.
Wenn ich versuche, das Verhalten zwischen zwei eng verwandten Klassen zu teilen, erstelle ich eine abstrakte Klasse, die das gemeinsame Verhalten enthält und beiden Klassen übergeordnet ist.
Wenn ich versuche, einen Typ zu definieren, eine Liste von Methoden, die ein Benutzer meines Objekts zuverlässig aufrufen kann, dann erstelle ich eine Schnittstelle.
Zum Beispiel würde ich niemals eine abstrakte Klasse mit einer konkreten Unterklasse erstellen, da es bei abstrakten Klassen um das Teilen von Verhalten geht. Aber ich könnte sehr gut eine Schnittstelle mit nur einer Implementierung erstellen. Der Benutzer meines Codes wird nicht wissen, dass es nur eine Implementierung gibt. Tatsächlich wird es in einer zukünftigen Version möglicherweise mehrere Implementierungen geben, die alle Unterklassen einer neuen abstrakten Klasse sind, die es bei der Erstellung der Schnittstelle noch nicht gab.
Das hätte vielleicht auch ein bisschen zu buchstäblich gewirkt (obwohl ich es noch nie so gesehen habe, wie ich mich erinnere). Wenn der Interviewer (oder das OP) wirklich mehr von meiner persönlichen Erfahrung dazu haben wollte, wäre ich mit Anekdoten einer Schnittstelle fertig geworden, die sich aus der Notwendigkeit heraus entwickelt hat und umgekehrt.
Noch eine Sache. Java 8 ermöglicht es Ihnen jetzt, Standardcode in eine Schnittstelle einzufügen, wodurch die Grenze zwischen Schnittstellen und abstrakten Klassen weiter verwischt wird. Aber nach allem, was ich gesehen habe, wird dieses Feature sogar von den Machern der Java Kernbibliotheken überbeansprucht. Diese Funktion wurde zu Recht hinzugefügt, um die Erweiterung einer Schnittstelle zu ermöglichen, ohne dass es zu einer binären Inkompatibilität kommt. Wenn Sie jedoch einen brandneuen Typ erstellen, indem Sie eine Schnittstelle definieren, sollte die Schnittstelle NUR eine Schnittstelle sein. Wenn Sie auch gemeinsamen Code bereitstellen möchten, erstellen Sie auf jeden Fall eine Hilfsklasse (abstrakt oder konkret). Überladen Sie Ihre Benutzeroberfläche nicht von Anfang an mit Funktionen, die Sie möglicherweise ändern möchten.
Der grundlegende Unterschied zwischen der Schnittstelle und der abstrakten Klasse besteht darin, dass die Schnittstelle Mehrfachvererbung unterstützt, die abstrakte Klasse jedoch nicht.
In abstract class können Sie auch alle abstrakten Methoden wie interface bereitstellen.
warum ist eine abstrakte Klasse erforderlich?
In einigen Szenarien weiß die abstrakte Klasse während der Verarbeitung der Benutzeranforderung nicht, welche Benutzerabsicht vorliegt. In diesem Szenario definieren wir eine abstrakte Methode in der Klasse und fragen den Benutzer, der diese Klasse erweitert, bitte geben Sie Ihre Absicht in der abstrakten Methode an. In diesem Fall sind abstrakte Klassen sehr nützlich
Warum ist eine Schnittstelle erforderlich?
Nehmen wir an, ich habe eine Arbeit, die ich in diesem Bereich nicht erlebt habe. Wenn Sie beispielsweise ein Gebäude oder einen Damm bauen möchten, was werden Sie dann in diesem Szenario tun?
Hier kümmere ich mich nicht um die Logik, wie sie aufgebaut sind. Das endgültige Objekt hat meine Anforderungen erfüllt oder nicht, dass nur mein entscheidender Punkt.
Hier werden Ihre Anforderungen als Schnittstelle und Konstruktoren als Implementierer bezeichnet.
Ich werde versuchen, anhand eines praktischen Szenarios zu antworten, um den Unterschied zwischen den beiden aufzuzeigen.
Schnittstellen kommen mit einer Nutzlast von Null, d. H., Es muss kein Zustand aufrechterhalten werden, und daher ist es die bessere Wahl, einen Vertrag (eine Fähigkeit) nur einer Klasse zuzuordnen.
Angenommen, ich habe eine Task-Klasse, die eine Aktion ausführt. Um jetzt eine Task in einem separaten Thread auszuführen, muss ich die Thread-Klasse nicht wirklich erweitern. Eine bessere Wahl ist, die Task-Schnittstelle Runnable implementieren zu lassen (dh ihre run () -Methode zu implementieren ) und übergeben Sie dann das Objekt dieser Task-Klasse an eine Thread-Instanz und rufen Sie die Methode start () auf.
Nun können Sie sich fragen, ob Runnable eine abstrakte Klasse war.
Nun, technisch war das möglich, aber in Bezug auf das Design wäre dies ein Grund für die schlechte Wahl gewesen:
Mit anderen Worten, die Task-Klasse benötigte eine Fähigkeit, in einem Thread ausgeführt zu werden, die durch die Implementierung von Runnable-Interface-Versen erreicht wurde, die die Thread-Klasse erweitern, die sie zu einem Thread machen würden.
Setzen Sie uns einfach eine Schnittstelle, um eine Fähigkeit (einen Vertrag) zu definieren, und verwenden Sie eine abstrakte Klasse, um die (gemeinsame/teilweise) Implementierung der Fähigkeit zu definieren.
Disclaimer: dummes Beispiel folgt, versuche nicht zu urteilen :-P
interface Forgiver {
void forgive();
}
abstract class GodLike implements Forgiver {
abstract void forget();
final void forgive() {
forget();
}
}
Jetzt haben Sie die Wahl, gottähnlich zu sein, aber Sie können sich auch dafür entscheiden, nur verzeihend zu sein (d. H. Nicht gottähnlich) und Folgendes tun:
class HumanLike implements Forgiver {
void forgive() {
// forgive but remember
}
}
Oder Sie können sich dafür entscheiden, gottähnlich zu sein und Folgendes zu tun:
class AngelLike extends GodLike {
void forget() {
// forget to forgive
}
}
P.S. mit Java 8-Schnittstelle kann auch statische als auch standardmäßige (überschreibbare Implementierungs-) Methoden haben, und daher wird der Unterschied zwischen S/W-Schnittstelle und abstrakter Klasse noch weiter eingegrenzt.
Ja, Ihre Antworten waren technisch korrekt, aber wo Sie falsch liefen, haben Sie nicht gezeigt, dass Sie die Vor- und Nachteile einer Auswahl vor der anderen verstehen. Darüber hinaus waren sie wahrscheinlich besorgt über die Kompatibilität ihrer Codebasis mit zukünftigen Upgrades. Diese Art der Antwort hat möglicherweise geholfen (zusätzlich zu dem, was Sie gesagt haben):
"Die Auswahl einer abstrakten Klasse gegenüber einer Interface - Klasse hängt davon ab, wie wir die Zukunft des Codes projizieren.
Abstrakte Klassen ermöglichen eine bessere Aufwärtskompatibilität, da Sie einer abstrakten Klasse auch in Zukunft Verhalten hinzufügen können, ohne den vorhandenen Code zu beschädigen -> dies ist mit einer Schnittstellenklasse nicht möglich.
Andererseits sind Schnittstellenklassen flexibler als abstrakte Klassen. Dies liegt daran, dass sie mehrere Schnittstellen implementieren können. Die Sache ist, dass Java keine Mehrfachvererbungen hat, sodass Sie bei Verwendung von abstrakten Klassen keine andere Klassenhierarchiestruktur verwenden können ...
Am Ende lautet die Faustregel also: Verwenden Sie lieber Schnittstellenklassen, wenn Ihre Codebasis keine vorhandenen/Standardimplementierungen enthält. Verwenden Sie abstrakte Klassen, um die Kompatibilität zu gewährleisten, wenn Sie wissen, dass Sie Ihre Klasse in Zukunft aktualisieren werden. "
Viel Glück beim nächsten Interview!
hmm, jetzt sind die Leute hungrig, praktisch, Sie haben völlig recht, aber die meisten Interviewer sehen nach ihren aktuellen Anforderungen aus und wollen einen praktischen Ansatz.
nach Beendigung Ihrer Antwort sollten Sie auf das Beispiel springen:
Abstract:
zum Beispiel haben wir eine Gehaltsfunktion, die allen Mitarbeitern gemeinsam ist. Dann können wir eine abstrakte Klasse namens CTC mit einem teilweise definierten Methodenkörper haben, die von jedem Mitarbeitertyp erweitert wird und entsprechend ihrer zusätzlichen Stärken neu definiert wird. Für die allgemeine Funktionalität.
public abstract class CTC {
public int salary(int hra, int da, int extra)
{
int total;
total = hra+da+extra;
//incentive for specific performing employee
//total = hra+da+extra+incentive;
return total;
}
}
class Manger extends CTC
{
}
class CEO extends CTC
{
}
class Developer extends CTC
{
}
Schnittstelle
die Schnittstelle in Java ermöglicht die Verwendung der Schnittstellenfunktionalität, ohne diese zu erweitern, und Sie müssen sich mit der Implementierung der Signatur der Funktionalität, die Sie in Ihre Anwendung einführen möchten, klar sein. es wird dich zwingen, definiton zu haben. Für verschiedene Funktionen.
public interface EmployeType {
public String typeOfEmployee();
}
class ContarctOne implements EmployeType
{
@Override
public String typeOfEmployee() {
return "contract";
}
}
class PermanentOne implements EmployeType
{
@Override
public String typeOfEmployee() {
return "permanent";
}
}
sie können eine solche erzwungene Aktivität auch mit einer abstrakten Klasse haben, indem Sie Methoden als eine abstrakte definieren. Jetzt erweitert eine Klasse die abstrakte Klasse als eine abstrakte, bis sie diese abstrakte Funktion überschreibt.
Fast alles scheint hier bereits behandelt zu sein. Noch ein Punkt zur praktischen Umsetzung der Klasse abstract
:
Das Schlüsselwort
abstract
wird auch verwendet, um zu verhindern, dass eine Klasse instanziiert wird. Wenn Sie eine konkrete Klasse haben, die Sie nicht instanziieren möchten, machen Sie sieabstract
.
Nach dem, was ich verstehe und wie ich vorgehe,
Interface ist wie eine Spezifikation/ein Vertrag. Jede Klasse, die eine Interface-Klasse implementiert, muss alle in der abstrakten Klasse definierten Methoden implementieren (mit Ausnahme der Standardmethoden (eingeführt in Java 8).
Während ich eine Klassenzusammenfassung definiere, wenn ich die für einige Methoden der Klasse erforderliche Implementierung und einige Methoden weiß, weiß ich immer noch nicht, was die Implementierung sein wird (wir kennen möglicherweise die Funktionssignatur, aber nicht die Implementierung). Ich mache das so, dass ich später in der Entwicklung, wenn ich weiß, wie diese Methoden implementiert werden sollen, diese abstrakte Klasse einfach erweitern und diese Methoden implementieren kann.
Hinweis: Sie können in Schnittstellenmethoden keinen Funktionsrumpf verwenden, es sei denn, die Methode ist statisch oder standardmäßig.
In der abstrakten Klasse können Sie die Standardimplementierung von Methoden schreiben! Aber im Interface kannst du nicht. Grundsätzlich existieren in interface rein virtuelle Methoden, die von der Klasse implementiert werden müssen, die das Interface implementiert.
Soweit ich weiß, wird eine Schnittstelle, die aus endgültigen Variablen und Methoden ohne Implementierungen besteht, von einer Klasse implementiert, um eine Gruppe von Methoden oder Methoden zu erhalten, die miteinander in Beziehung stehen. Andererseits wird eine abstrakte Klasse, die nicht endgültige Variablen und Methoden mit Implementierungen enthalten kann, normalerweise als Leitfaden oder als Superklasse verwendet, von der alle verwandten oder ähnlichen Klassen erben. Mit anderen Worten, eine abstrakte Klasse enthält alle Methoden/Variablen, die von allen Unterklassen gemeinsam genutzt werden.
Ich glaube, was der Interviewer versucht hat, war wahrscheinlich der Unterschied zwischen Schnittstelle und Implementierung.
Die Schnittstelle - keine Java -Schnittstelle, sondern allgemein "Schnittstelle" - zu einem Codemodul ist im Grunde der Vertrag mit Clientcode, der die Schnittstelle verwendet.
Die Implementierung eines Codemoduls ist der interne Code, mit dem das Modul funktioniert. Häufig können Sie eine bestimmte Schnittstelle auf mehrere Arten implementieren und sogar die Implementierung ändern, ohne dass der Client-Code die Änderung überhaupt bemerkt.
Eine Java -Schnittstelle sollte nur als Schnittstelle im oben genannten allgemeinen Sinne verwendet werden, um zu definieren, wie sich die Klasse zugunsten des Clientcodes mithilfe der Klasse verhält, ohne dass eine Implementierung angegeben wird. Daher enthält eine Schnittstelle Methodensignaturen - die Namen, Rückgabetypen und Argumentlisten - für Methoden, von denen erwartet wird, dass sie vom Client-Code aufgerufen werden. Grundsätzlich sollte jede Methode über genügend Javadoc verfügen, um die Funktionsweise dieser Methode zu beschreiben. Der überzeugendste Grund für die Verwendung einer Schnittstelle besteht darin, dass Sie mehrere verschiedene Implementierungen der Schnittstelle planen und abhängig von der Bereitstellungskonfiguration möglicherweise eine Implementierung auswählen.
Im Gegensatz dazu bietet eine abstrakte Klasse Java eine teilweise Implementierung der Klasse, anstatt in erster Linie eine Schnittstelle anzugeben. Es sollte verwendet werden, wenn mehrere Klassen Code gemeinsam nutzen, aber auch erwartet wird, dass die Unterklassen einen Teil der Implementierung bereitstellen. Auf diese Weise wird der gemeinsam genutzte Code nur an einer Stelle angezeigt - der abstrakten Klasse - und es wird klargestellt, dass Teile der Implementierung in der abstrakten Klasse nicht vorhanden sind und voraussichtlich von Unterklassen bereitgestellt werden.
ihre Antwort ist richtig, aber der Interviewer möchte, dass Sie nach der Perspektive der Softwareentwicklung und nicht nach den Details von Java differenzieren.
Einfache Worte:
Ein Interface ist wie das Interface eines Shops. Alles, was darauf gezeigt wird, sollte im Shop vorhanden sein. Daher muss jede Methode im Interface in der konkreten Klasse implementiert sein. Was nun, wenn einige Klassen einige exakte Methoden teilen und in anderen variieren? Angenommen, das Interface handelt von einem Geschäft, das zwei Dinge enthält. Angenommen, wir haben zwei Geschäfte, die beide Sportausrüstung enthalten, aber einer hat Kleidung und der andere Schuhe. Sie erstellen also eine abstrakte Klasse für Sport, die die Sports-Methode implementiert und die andere Methode nicht implementiert. Abstrakte Klasse bedeutet hier, dass dieser Shop selbst nicht existiert, aber die Basis für andere Klassen/Shops ist. Auf diese Weise organisieren Sie den Code, vermeiden Fehler beim Replizieren des Codes, vereinheitlichen den Code und stellen die Wiederverwendbarkeit durch eine andere Klasse sicher.