Vielleicht hätte ich nicht mehrere Fragen mischen sollen. Aber sie hängen eben zusammen. Vielleicht ist auch aus einem anderen Grund nicht klar geworden, worauf ich raus will.
Angenommen, es soll eine Utility-Library geben. Die könnte komplett generisch sein. Sie könnte nur auf den Interfaces der Standard-API aufbauen. Im speziellen sollte sie keine dependency zu einer Library haben, wo irgendeine ominöse, höchst-spezifische CustomerMeasure
rumliegt.
(Sie braucht dieses interface auch nicht, weil es strukturell gleich zu einer ToDoubleFunction
ist, und das ist es, was die Library mindestens braucht. Es gibt weitere (gute!) Gründe, aber belassen wir es mal dabei.)
D.h. man könnte darin eine Methode schreiben wie
<T> void doSomething(List<? extends ToDoubleFunction<? super T>> list, T t){...}
Häßlich, durch die ? extends/ ? super
-Gymnastik, aber schön, weil es dependency-frei und generisch ist. Die Priorität liegt hier auf letzterem.
Nun soll es eine andere „Application“-Library geben. Die hat zum Beispiel eine CustomerMeasure
, weil sich das leichter liest, weil es die „Domäneninformation“ transportiert, und damit implizit auch dokumentiert.
(Welche Rolle da das ObjectMeasure<T>
spielt, sei jetzt mal egal. Entscheidend ist: Das CustomerMeasure
ist strukturell gleich zu einer ToDoubleFunction<Customer>
)
Der Benutzer dieser Library braucht nicht zu schreiben
List<ToDoubleFunction<Customer>> measures = ...;
sondern er kann schreiben
List<CustomerMeasure> measures = ...;
Letzeres ist besser lesbar, und für die Application-Library steht die Lesbarkeit und einfache Benutzbarkeit im Vordergrund.
(Das oben noch eins der einfachsten Beispiele. Dass das Bedürfnis, einem Ding wie ToDoubleBiFunction<Collection<? extends Number>, Collection<? extends Number>>
einen sprechenden, einfachen Namen wie NumberCollectionAdder
zu geben, noch größer ist, sollte klar sein)
Und einer der Kernpunkte dieser Frage (wenn auch leider nicht der einzige) ist eben:
List<ToDoubleFunction<Customer>> functions = ...;
Utility.doSomething(functions, c); // Das geht
List<CustomerMeasure> measures = ...;
Utility.doSomething(measures , c); // Das geht NICHT!!!
Letzteres ginge nur, wenn man CustomerMeasure extends ToDoubleFunction<Customer>
festlegt.