webentwicklung-frage-antwort-db.com.de

Warum kann eine abstrakte Klasse, die eine Schnittstelle implementiert, die Deklaration / Implementierung einer der Methoden der Schnittstelle verpassen?

Eine merkwürdige Sache passiert in Java, wenn Sie eine abstrakte Klasse verwenden, um eine Schnittstelle zu implementieren: Einige der Methoden der Schnittstelle können vollständig fehlen (dh es ist weder eine abstrakte Deklaration noch eine tatsächliche Implementierung vorhanden), aber Der Compiler beschwert sich nicht.

Zum Beispiel angesichts der Schnittstelle:

public interface IAnything {
  void m1();
  void m2();
  void m3();
}

die folgende abstrakte Klasse wird ohne Warnung oder Fehler fröhlich kompiliert:

public abstract class AbstractThing implements IAnything {
  public void m1() {}
  public void m3() {}
}

Kannst du erklären warum?

120

Wenn eine Klasse abstrakt ist, müssen Sie per Definition Unterklassen erstellen, um sie zu instanziieren. Die Unterklassen müssen (vom Compiler) alle Schnittstellenmethoden implementieren, die von der abstrakten Klasse ausgelassen wurden.

Versuchen Sie, Ihrem Beispielcode folgend eine Unterklasse von AbstractThing zu erstellen, ohne die Methode m2 Zu implementieren, und überprüfen Sie, welche Fehler der Compiler Ihnen liefert. Sie werden gezwungen, diese Methode zu implementieren.

150
Bill the Lizard

Völlig in Ordnung.
Sie können keine abstrakten Klassen instanziieren. Aber abstrakte Klassen können verwendet werden, um allgemeine Implementierungen für m1 () und m3 () aufzunehmen.
Also , wenn m2 () für jede Implementierung unterschiedlich ist, m1 und m3 jedoch nicht. Sie könnten verschiedene konkrete IAnything-Implementierungen mit nur der unterschiedlichen m2-Implementierung erstellen und von AbstractThing ableiten - wobei Sie das DRY) -Prinzip einhalten. Die Überprüfung, ob die Schnittstelle für eine abstrakte Klasse vollständig implementiert ist, ist vergeblich.

pdate: Interessanterweise erzwingt C # dies als Kompilierungsfehler. In diesem Szenario müssen Sie die Methodensignaturen kopieren und ihnen das Präfix 'abstract public' in der abstrakten Basisklasse voranstellen.

33
Gishu

Das ist gut. Um das oben Genannte zu verstehen, müssen Sie zuerst die Natur abstrakter Klassen verstehen. Sie ähneln in dieser Hinsicht Schnittstellen. Dies ist, was Oracle dazu sagt hier .

Abstrakte Klassen ähneln Schnittstellen. Sie können sie nicht instanziieren, und sie können eine Mischung von Methoden enthalten, die mit oder ohne Implementierung deklariert wurden.

Sie müssen sich also überlegen, was passiert, wenn eine Schnittstelle eine andere Schnittstelle erweitert. Beispielsweise ...

//Filename: Sports.Java
public interface Sports
{
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}

//Filename: Football.Java
public interface Football extends Sports
{
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}

... wie Sie sehen können, kompiliert dies auch einwandfrei. Ganz einfach, weil eine Schnittstelle wie eine abstrakte Klasse NICHT instanziiert werden kann. Daher ist es nicht erforderlich, die Methoden des übergeordneten Elements explizit zu erwähnen. ALLE übergeordneten Methodensignaturen werden jedoch implizit Teil der Erweiterungsschnittstelle oder der implementierenden abstrakten Klasse. Sobald eine geeignete Klasse (eine, die instanziiert werden kann) die obige erweitert, muss sichergestellt werden, dass jede einzelne abstrakte Methode implementiert wird.

Hoffe das hilft ... und Allahu 'alam!

7
Grateful

Interface bedeutet eine Klasse, die keine Implementierung ihrer Methode hat, sondern nur eine Deklaration.
Andererseits ist eine abstrakte Klasse eine Klasse, die eine Implementierung einer Methode zusammen mit einer Methode mit nur einer Deklaration und keiner Implementierung haben kann.
Wenn wir eine Schnittstelle zu einer abstrakten Klasse implementieren, bedeutet dies, dass die abstrakte Klasse alle Methoden der Schnittstelle geerbt hat. Da es nicht wichtig ist, alle Methoden in einer abstrakten Klasse zu implementieren, sondern in einer abstrakten Klasse (auch durch Vererbung), kann die abstrakte Klasse einen Teil der Methode in der Schnittstelle belassen, ohne dies hier zu implementieren. Aber wenn diese abstrakte Klasse von einer konkreten Klasse geerbt wird, müssen sie alle diese nicht implementierten Methoden in der abstrakten Klasse implementieren.

4

Angesichts der Schnittstelle:

public interface IAnything {
  int i;
  void m1();
  void m2();
  void m3();
}

So sieht es Java eigentlich:

public interface IAnything {
  public static final int i;
  public abstract void m1();
  public abstract void m2();
  public abstract void m3();
}

Sie können also einige (oder alle) dieser abstract Methoden nicht implementieren, genau wie Sie dies bei abstract Klassen tun würden, die eine andere abstract Klasse erweitern.

Wenn Sie implement und interface, gilt die Regel, dass alle interface Methoden in den abgeleiteten class implementiert werden müssen, nur für konkrete class Implementierung (dh die nicht abstract selbst ist).

Wenn Sie tatsächlich vorhaben, ein abstract class aus, dann gibt es keine Regel, die besagt, dass Sie implement alle interface Methoden anwenden müssen (beachten Sie, dass in einem solchen Fall die Angabe des abgeleiteten class als abstract)

4
sharhp

Wenn eine abstrakte Klasse eine Schnittstelle implementiert

Im Abschnitt zu Schnittstellen wurde darauf hingewiesen, dass eine Klasse, die eine Schnittstelle implementiert, alle Methoden der Schnittstelle implementieren muss. Es ist jedoch möglich, eine Klasse zu definieren, die nicht alle Methoden der Schnittstelle implementiert, sofern die Klasse als abstrakt deklariert ist. Beispielsweise,

abstract class X implements Y {   
    // implements all but one method of Y
}
class XX extends X {   
    // implements the remaining method in Y 
} 

In diesem Fall muss Klasse X abstrakt sein, da sie Y nicht vollständig implementiert, Klasse XX jedoch Y tatsächlich implementiert.

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

2
D Vy

Abstrakte Klassen sind nicht erforderlich, um die Methoden zu implementieren. Obwohl eine Schnittstelle implementiert wird, können die abstrakten Methoden der Schnittstelle abstrakt bleiben. Wenn Sie versuchen, eine Schnittstelle in einer konkreten Klasse (d. H. Nicht abstrakt) zu implementieren, und Sie die abstrakten Methoden nicht implementieren, teilt Ihnen der Compiler Folgendes mit: Implementieren Sie entweder die abstrakten Methoden oder deklarieren Sie die Klasse als abstrakt.

1