Ich entwickle Code, der Generika verwendet, und eines meiner Leitprinzipien war es, ihn für zukünftige Szenarien und nicht nur für heutige Szenarien nutzbar zu machen. Mehrere Mitarbeiter haben jedoch zum Ausdruck gebracht, dass ich die Lesbarkeit möglicherweise aus Gründen der Erweiterbarkeit abgewogen habe. Ich wollte Feedback zu möglichen Lösungsmöglichkeiten einholen.
Um genau zu sein, hier ist eine Schnittstelle, die eine Transformation definiert: Sie beginnen mit einer Quellensammlung von Elementen und wenden die Transformation auf jedes Element an, wobei die Ergebnisse in einer Zielsammlung gespeichert werden. Außerdem möchte ich in der Lage sein, die Zielsammlung an den Anrufer zurückzugeben, und anstatt sie zu zwingen, eine Sammlungsreferenz zu verwenden, möchte ich, dass sie den Sammlungstyp verwenden können, den sie tatsächlich für die Zielsammlung bereitgestellt haben.
Schließlich mache ich es möglich, dass sich die Art der Elemente in der Zielsammlung von der Art der Elemente in der Quellensammlung unterscheidet, da dies möglicherweise die Transformation bewirkt. In meinem Code bilden beispielsweise mehrere Quellelemente nach der Transformation ein Zielelement.
Dies ergibt die folgende Schnittstelle:
interface Transform<Src, Dst> {
<DstColl extends Collection<? super Dst>> DstColl transform(
Collection<? extends Src> sourceCollection,
DstColl destinationCollection);
}
Ich habe versucht, alle nett zu sein und das PECS-Prinzip von Josh Bloch (Produzent erweitert, Verbraucher super) anzuwenden, um sicherzustellen, dass die Schnittstelle gegebenenfalls mit Super- und Subtypen verwendet werden kann. Das Endergebnis ist eine Art Monstrosität.
Nun wäre es schön gewesen, wenn ich diese Schnittstelle erweitern und irgendwie spezialisieren könnte. Wenn es mir zum Beispiel nicht wirklich wichtig ist, mit Untertypen der Quellelemente und Supertypen der Zielelemente gut zu spielen, könnte ich Folgendes haben:
interface SimpleTransform<Src, Dst> {
<DstColl extends Collection<Dst>> DstColl transform(
Collection<Src> sourceCollection,
DstColl destinationCollection);
}
In Java gibt es dafür keine Möglichkeit. Ich möchte Implementierungen dieser Schnittstelle zu etwas machen, das andere tatsächlich in Betracht ziehen würden, anstatt in Angst zu laufen. Ich habe mehrere Optionen in Betracht gezogen:
- Geben Sie die Zielsammlung nicht zurück. Scheint seltsam, wenn man bedenkt, dass man eine Transformation durchführt, aber nichts zurückbekommt.
- Haben Sie eine abstrakte Klasse, die diese Schnittstelle implementiert, aber dann die Parameter in etwas einfacher zu übersetzendes übersetzt und eine andere Methode "translateImpl ()" aufruft, die die einfachere Signatur hat und somit für Implementierer eine geringere kognitive Belastung darstellt. Aber dann ist es seltsam, eine abstrakte Klasse schreiben zu müssen, um eine Benutzeroberfläche benutzerfreundlich zu gestalten.
- Verzichten Sie auf Erweiterbarkeit und haben Sie einfach die einfachere Oberfläche. Koppeln Sie dies möglicherweise damit, dass die Zielsammlung nicht zurückgegeben wird. Aber das schränkt meine Möglichkeiten in der Zukunft ein.
Was denken Sie? Fehlt mir ein Ansatz, den ich verwenden könnte?
Collection<? extends Src> srcCollection
sollten SieIterable<? extends Src>