Überschreiben des Rückgabetyps in der erweiterten Schnittstelle – Schlechte Idee?

In Java können Sie Folgendes tun:

public interface IEngine{} public interface ICoolEngine extends IEngine{} public interface Car { IEngine getEngine(); } public interface ICoolCar extends ICar { @Override ICoolEngine getEngine(); } 

Während dies ein Problem behebt, mit dem ich mich auseinandergesetzt habe, “fühlt sich etwas falsch an”.

Mache ich hier einen fiesen Design-Fauxpas?

Nein, du machst das Richtige. Kovariante Returns geben nur an, dass die class und die darunter liegenden classn eine bestimmte Unterklasse des ursprünglichen allgemeinen classnarguments zurückgeben müssen, das die Elternklasse zurückgegeben hat. Dies bedeutet auch, dass Ihre Unterklassen immer noch mit der ursprünglichen Schnittstelle kompatibel sind, die eine Engine zurückgeben muss. Wenn Sie jedoch wissen, dass es eine ICoolCar ist, verfügt sie über eine ICoolEngine – weil die spezifischere Schnittstelle spezifischere functionen kennt. Dies gilt sowohl für Schnittstellen als auch für classn – das ist korrekt, korrekt und nützlich zum Booten.

Nein. Das ist in Ordnung. Da ICoolEngine erweitert, kann jedes Objekt, das ICoolEngine implementiert, so behandelt werden, als ob es eine IEngine ( IEngine ohne alle ICoolEngine Methoden). Sie müssen sich lediglich des ICoolEngine bewusst sein, abhängig davon, mit welcher Schnittstelle Sie in jeder Situation arbeiten, und stellen Sie sicher, dass Sie keine ICoolEngine Methoden verwenden, die nicht in IEngine definiert IEngine (vorausgesetzt, in Ihrem tatsächlichen Code gibt es zusätzliche Methoden, die in der Entsprechung von ICoolEngine ).

Es ist keine schlechte Übung, dies zu tun; Sie benutzen einfach die Kraft des Polymorphismus.

Covariant-Rückgabetypen ist eine absichtliche function, die in 1.5 hinzugefügt wurde (hauptsächlich um Generika zu unterstützen).

@Override funktioniert möglicherweise nicht für das Überschreiben von abstrakten Methoden mit einigen Compilern (javac wurde in 1.6 aktualisiert, aber die JLS-Änderung wurde verpasst).

Das Hinzufügen einer Methode zu einer Schnittstelle birgt immer das Risiko von Kompatibilitätsproblemen. Eine Methode genau wie im Super-Typ zu deklarieren wäre in Ordnung, aber das Ändern des Rückgabetyps verursacht eine Bridge-Methode in Implementierungsklassen. Aus diesem Grund gibt Iterable.iterator keine schreibgeschützte Version der Iterator Schnittstelle zurück.

Was Sie tun, ist völlig in Ordnung.

Ich würde es lieber so sagen:

 public interface IEngine { } public interface ICoolEngine extends IEngine { } public interface ICar { T getEngine(); } public interface ICoolCar extends ICar { } 

Ich habe Generika verwendet, da Sie, wie Sie eine Anmerkung verwendet haben, angenommen haben, dass Sie an Java 5+ arbeiten