Warum ist “erweitert T” erlaubt, aber nicht “implementiert T”?

Lesezeit: 5 Minuten

Benutzer-Avatar
Benutzer120623

Gibt es in Java einen besonderen Grund, immer “extends” eher, als “implements” zum Definieren von Grenzen von Typparametern?

Zum Beispiel:

public interface C {}
public class A<B implements C>{} 

ist verboten, aber

public class A<B extends C>{} 

ist richtig. Was ist der Grund dafür?

  • Ich weiß nicht, warum die Leute denken, dass die Antwort von Tetsujin no Oni die Frage wirklich beantwortet. Es formuliert die Beobachtungen von OP im Grunde mit akademischen Formulierungen um, enthält jedoch keine Begründung. „Warum gibt es keine implements?” – “Weil es nur gibt extends“.

    – ThomasR

    21. September 2016 um 7:02 Uhr


  • ThomasR: Das liegt daran, dass es nicht um “erlaubt” geht, sondern um die Bedeutung: Es gibt keinen Unterschied darin, wie Sie ein generisches schreiben würden, das einen Typ mit einer Einschränkung verbraucht, ob die Einschränkung von einer Schnittstelle oder einem Vorfahrentyp stammt.

    – Tetsujin no Oni

    6. Oktober 2016 um 15:53 ​​Uhr

  • Eine Antwort (stackoverflow.com/a/56304595/4922375) mit meiner Begründung hinzugefügt implements würde nichts Neues bringen und die Sache noch komplizierter machen. Ich hoffe, es wird für Sie hilfreich sein.

    – Andreas Tobilko

    25. Mai 2019 um 12:15 Uhr

Benutzer-Avatar
Tetsujin no Oni

Es gibt keinen semantischen Unterschied in der generischen Constraint-Sprache, ob eine Klasse „implementiert“ oder „erweitert“. Die Einschränkungsmöglichkeiten sind ‘extends’ und ‘super’ – das heißt, ist diese Klasse, mit der gearbeitet werden soll, der anderen zuweisbar (extends), oder ist diese Klasse dieser Klasse zuweisbar (super).

  • @KomodoDave (Ich denke, die Zahl neben der Antwort markiert sie als richtig, ich bin mir nicht sicher, ob es eine andere Möglichkeit gibt, sie zu markieren, manchmal können andere Antworten zusätzliche Informationen enthalten – z. B. hatte ich ein bestimmtes Problem, das ich nicht lösen konnte, und Google schickt Sie hierher, wenn Sie danach suchen.) @Tetsujin no Oni (Wäre es möglich, einen Code zur Klärung zu verwenden? Danke :))

    – ntg

    12. Mai 2014 um 0:38 Uhr


  • @ntg, dies ist ein sehr gutes Beispiel für eine Frage, die nach Beispielen sucht – ich werde es im Kommentar verlinken, anstatt es an dieser Stelle in die Antwort einzubetten. stackoverflow.com/a/6828257/93922

    – Tetsujin no Oni

    20. Oktober 2014 um 13:44 Uhr

  • Ich denke, der Grund ist, dass ich zumindest ein Generikum haben möchte, das einen Konstruktor und Methoden haben kann, die jede Klasse akzeptieren können, die sowohl eine Basisklasse erweitert als auch eine Schnittstelle aufweist, nicht nur Schnittstellen, die eine Schnittstelle erweitern. Lassen Sie dann die Instanziierung des Genric-Tests auf das Vorhandensein von Schnittstellen UND die tatsächliche Klasse als Typparameter angeben. Idealerweise möchte ich class Generic<RenderableT extends Renderable implements Draggable, Droppable, ...> { Generic(RenderableT toDrag) { x = (Draggable)toDrag; } } Man will Compile-Time-Checks.

    – Peterk

    5. Mai 2016 um 3:04 Uhr


  • @peterk Und das bekommen Sie mit RenderableT erweitert Renderable, Draggable, Droppable … es sei denn, ich verstehe nicht, was die Löschgenerika für Sie tun sollen, die dies nicht bietet.

    – Tetsujin no Oni

    5. Mai 2016 um 17:54 Uhr

  • @TetsujinnoOni Sie wollen nicht, dass bei der Kompilierung nur Klassen akzeptiert werden, die einen bestimmten Satz von Schnittstellen implementieren, und dann in der Lage sind, auf die OBJECT-Klasse (die diese Schnittstellen aufweist) im Generikum zu verweisen und das dann zu wissen zumindest zur Kompilierzeit ( und wünschenswerterweise zur Laufzeit ) kann alles, was dem Generikum zugewiesen ist, sicher in eine der angegebenen Schnittstellen umgewandelt werden. Dies ist bei der jetzigen Implementierung von Java nicht der Fall. Aber schön wäre es 🙂

    – Peterk

    7. Mai 2016 um 3:13 Uhr

Wahrscheinlich, weil für beide Seiten (B und C) nur der Typ relevant ist, nicht die Implementierung. In deinem Beispiel

public class A<B extends C>{}

B kann auch eine Schnittstelle sein. “extends” wird verwendet, um Unterschnittstellen sowie Unterklassen zu definieren.

interface IntfSub extends IntfSuper {}
class ClzSub extends ClzSuper {}

Normalerweise denke ich an „Sub erweitert Super“ als „Sub ist wie Superaber mit zusätzlichen Fähigkeiten’ und ‘Clz implementiert Intf’ als ‘Clz ist eine Erkenntnis von Intf‘. In Ihrem Beispiel würde dies übereinstimmen: B ist wie C, aber mit zusätzlichen Funktionen. Hier sind die Fähigkeiten relevant, nicht die Realisierung.

  • Betrachten Sie . E darf nicht eine Klasse sein.

    – Tom Hawtin – Angelleine

    19. Juni 2009 um 20:29 Uhr

  • @TomHawtin-tackline Abgesehen davon, dass Sie anscheinend keinen Typparameter (“E”) verwenden können, müssen Sie nach diesem kaufmännischen Und-Zeichen ein Schnittstellenliteral einfügen, damit Java Ihnen vertrauen kann, dass es sich um eine Schnittstelle handelt. Hier würde ich mich gerne korrigieren lassen.

    – Jaroslav Zaruba

    26. September 2020 um 20:16 Uhr

  • @JaroslavZáruba Das stimmt. Tatsächlicher Fehler ist “unerwarteter Typ erforderlich: Klasse gefunden: Typparameter E” (meine Betonung liegt auf ‘Klasse’). Auf dem Originalposter wurden jedoch (leider) einzelne Buchstaben für Typnamen sowie Typparameter = verwendet E soll bedeuten, einen tatsächlichen Typnamen zu schreiben (ich glaube – ich habe diesen Kommentar vor über einem Jahrzehnt geschrieben).

    – Tom Hawtin – Angelleine

    27. September 2020 um 12:43 Uhr

  • @TomHawtin-tackline verdammt, ich hatte gehofft, es könnte eine Problemumgehung geben 🙂

    – Jaroslav Zaruba

    28. September 2020 um 14:36 ​​Uhr

Es ist irgendwie willkürlich, welche der Begriffe verwendet werden sollen. Es hätte so oder so sein können. Vielleicht dachten die Sprachdesigner „erweitert“ als den grundlegendsten Begriff und „implementiert“ als den Spezialfall für Schnittstellen.

Aber ich denke implements würde etwas mehr Sinn machen. Ich denke, das kommuniziert mehr, dass die Parametertypen nicht in einer Vererbungsbeziehung stehen müssen, sie können es sein irgendein eine Art Subtypenbeziehung.

Das Java-Glossar drückt a ähnliche Ansicht.

  • Betrachten Sie . E darf nicht eine Klasse sein.

    – Tom Hawtin – Angelleine

    19. Juni 2009 um 20:29 Uhr

  • @TomHawtin-tackline Abgesehen davon, dass Sie anscheinend keinen Typparameter (“E”) verwenden können, müssen Sie nach diesem kaufmännischen Und-Zeichen ein Schnittstellenliteral einfügen, damit Java Ihnen vertrauen kann, dass es sich um eine Schnittstelle handelt. Hier würde ich mich gerne korrigieren lassen.

    – Jaroslav Zaruba

    26. September 2020 um 20:16 Uhr

  • @JaroslavZáruba Das stimmt. Tatsächlicher Fehler ist “unerwarteter Typ erforderlich: Klasse gefunden: Typparameter E” (meine Betonung liegt auf ‘Klasse’). Auf dem Originalposter wurden jedoch (leider) einzelne Buchstaben für Typnamen sowie Typparameter = verwendet E soll bedeuten, einen tatsächlichen Typnamen zu schreiben (ich glaube – ich habe diesen Kommentar vor über einem Jahrzehnt geschrieben).

    – Tom Hawtin – Angelleine

    27. September 2020 um 12:43 Uhr

  • @TomHawtin-tackline verdammt, ich hatte gehofft, es könnte eine Problemumgehung geben 🙂

    – Jaroslav Zaruba

    28. September 2020 um 14:36 ​​Uhr

Benutzer-Avatar
Tom Hawtin – Tackline

Es kann sein, dass der Basistyp ein generischer Parameter ist, sodass der eigentliche Typ eine Schnittstelle einer Klasse sein kann. Prüfen:

class MyGen<T, U extends T> {

Auch aus der Client-Code-Perspektive sind Schnittstellen kaum von Klassen zu unterscheiden, während dies für Untertypen wichtig ist.

1006670cookie-checkWarum ist “erweitert T” erlaubt, aber nicht “implementiert T”?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy