Ich habe zwei Schnittstellen in Java (Version 8), die sehr ähnlich sind. Ich kann die Schnittstellen nicht ändern und kann die Klassen, die sie implementieren, nicht ändern.
public interface A {
int get();
}
public interface B {
int get();
int somethingelse();
}
Jetzt habe ich eine Funktion, deren Implementierung (fast) auf beide Schnittstellen passt. Ich möchte, dass es so etwas macht:
public int foo((A | B) p) {
int ret = 0;
if (p instanceof B) {
ret = p.somthingelse();
}
return ret + p.get();
}
Ich möchte keine Inspektion verwenden, da sich diese Funktion in der Hauptpipeline meines Programms befindet. Ich möchte, dass es eine gute Leistung hat. Ist das in Java möglich?
Bearbeiten:
Eine einfache Lösung besteht darin, foo()
sie für jede Schnittstelle anders zu kopieren / einzufügen und zu implementieren. Aber in Wirklichkeit sind foo()
die Schnittstellen viel länger und ich versuche, Codeduplikationen zu vermeiden.
get()
gemeinsam. Dies ist natürlich ein vereinfachtes Beispiel. In Wirklichkeit haben sie mehr Funktionen gemeinsam.public
Accessor ist für Schnittstellenmethoden redundant. Und meintest duinstanceof
stattimplements
?Antworten:
Es gibt leider keine Möglichkeit, eine solche rückwirkende Beziehung zwischen zwei nicht verwandten Typen herzustellen.
Wenn Sie Änderungen
foo()
und deren Aufrufe vornehmen können, können Sie möglicherweise funktionale Schnittstellen verwenden, die mit den Signaturen übereinstimmen, die Sie im Inneren aufrufenfoo
. Ich verwendeIntSupplier
hier mit entsprechenden Lambda-Ausdrücken konkrete Implementierungen vonA
undB
.Angenommen, Sie haben diese Implementierungen:
Sie können
foo
zu etwas wechseln wie:Und nenne es so:
quelle
foo()
für jede Schnittstelle und rufen Sie dannfoo()
mit passenden Lieferanten an. Möchten Sie dies hinzufügen oder möchten Sie, dass ich Ihre Antwort bearbeite?if
Logik im Inneren bleiben mussfoo()
. Aber ja, das können Sie definitiv tun, wenn es angebracht ist.IntSupplier
in dieser Antwort auf die Frage und den Vorschlag beziehen kann . Darüber hinaus kann dasBImpl
(oder einfachB
) nicht als FunctionalInterface verwendet werden, wenn mehr als eine abstrakte Methode vorhanden ist. Aus einem Kommentar geht hervor , dass die Aussage " zwei nicht verwandte Typen " nicht zutrifft. Nitpick:IntSupplier get
wird in Ihrem Code nicht verwendet.B
wird nicht als funktionale Schnittstelle verwendet.b:somethingelse
istIntSupplier
in diesem Fall eine Methodenreferenz (ich würde vorschlagen, dass Sie den Code kompilieren). Und ja,A
und esB
gibt zwei völlig unabhängige Typen. Und was die Lösung insgesamt betrifft, denke ich, dass Sie es etwas umständlich finden. Ich kann annehmen, dass es feinere Ansätze gibt, aber nicht viele, die das Refactoring meiden, das sich das OP nicht leisten kann.Ich kann mir nur Folgendes vorstellen:
quelle
Afaik, Java unterstützt dies nicht direkt, aber Sie können manuell einen "Type-Union-Wrapper" erstellen. Etwas wie das:
Sie können auch einige Inspektionsfunktionen hinzufügen
hasSomethingElse()
, z. B. wenn kein geeigneter Standardwert zurückgegeben werden soll, wie0
oben.quelle