Dlaczego metody fabryki narzędzi często używają określonego parametru ogólnego (np. T
) zamiast ograniczonego parametru wieloznacznego (np. ? super T
)?W guava, dlaczego jest po prostu "T", gdzie "? Super T" byłoby możliwe?
Na przykład, podpis Functions#forPredicate jest:
public static <T> Function<T, Boolean> forPredicate(Predicate<T> predicate)
Dlaczego nie używać:
public static <T> Function<T, Boolean> forPredicate(Predicate<? super T> predicate)
co czyniłoby coś jak następuje możliwe?
Predicate<Number> isPositivePredicate = ...
Function<Integer, Boolean> isPositiveInteger = Functions.forPredicate(isPositivePredicate);
// above line is compiler error:
// Type mismatch: cannot convert from Function<Number,Boolean> to Function<Integer,Boolean>
Czy dlatego oczekuje się konsumenci z Function
i Predicate
mieć ograniczony niezbędnych parametrów zastępczych, aby to niepotrzebne? Na przykład, ogólne granice na Iterables#find pozwoliłby Predicate<Number>
być stosowany na Iterable<Integer>
:
public static <T> T find(Iterable<T> iterable,
Predicate<? super T> predicate)
Czy istnieją inne powody?
re. po pierwsze, czy to nie tylko popycha konsumenta do rzucenia, co jest gorsze od dwóch zła? Co ciekawe, kiedy mówisz "my", masz na myśli to, że rozwinęłaś się w tej lub tylko społeczności oprogramowania w ogóle. – djechlin
Bardziej konkretnie - w jaki sposób ta polityka została spłacona w praktyce? Obecnie jedyne sytuacje, w których mogę sobie wyobrazić, że to ważne, konsument po prostu ominąłby casting do typu pochodnego. – djechlin
Kiedy mówię "my", mam na myśli to, że jestem w zespole Google Java Core Libraries, który rozwija Guava. Ale konsument nie powinien nigdy rzucać: 'Predicate super T>' może być zawsze użyty bezpośrednio, gdziekolwiek byś użył 'Predicate'. Nie ma potrzeby rzucania; można je zastosować dokładnie do tych samych wartości. –