Я могу написать метод, который принимает List
, элементы которого расширяют заданный базовый класс, например:
class BaseClass { }
class SubClass extends BaseClass { }
static void listMethod(List<? extends BaseClass> list) { }
Вызов этого метода прост и работает так, как ожидалось:
List<BaseClass> b = Collections.empty();
List<SubClass> s = Collections.empty();
listMethod(b); // ok
listMethod(s); // ok
Теперь я хотел бы изменить свой метод так, чтобы он принимал не List
, а вместо этого Observable
, который испускает List
. Таким образом, подпись меняется на:
static void observableListMethod(Observable<List<? extends BaseClass>> listObservable) { }
К сожалению, попытки вызвать этот новый метод приводят к ошибкам несоответствия аргументов вида:
Observable<List<BaseClass>> cannot be converted to Observable<List<? extends BaseClass>>
В отличие от общей проблемы с универсальными коллекциями в Java проблема здесь, по-видимому, не в неправильном приведении допущений между коллекциями подклассов и базовых классов. Скорее, это больше связано с конкретным типом используемого Observable.
Observable<List<BaseClass>> b = Observable.just(Collections.emptyList());
Observable<List<SubClass>> s = Observable.just(Collections.emptyList());
observableListMethod(b); // argument mismatch / incompatible types
observableListMethod(s); // argument mismatch / incompatible types
// I can map the List to a read-only variant...
observableListMethod(b.map(Collections::unmodifiableList)); // ok (for readonly)
observableListMethod(s.map(Collections::unmodifiableList)); // ok (for readonly)
Лучшее решение, которое я придумал до сих пор, — это изменить сигнатуру метода, чтобы указать конкретно BaseClass
(не ? extends BaseClass
), а затем выполнить некрасивую распаковку и преобразование List
с помощью Rx:
static void observableListMethod2(Observable<List<BaseClass>> listObservable) { }
public static void callObservableListMethod2() {
Observable<List<BaseClass>> b = Observable.just(Collections.emptyList());
Observable<List<SubClass>> s = Observable.just(Collections.emptyList());
observableListMethod2(b); // ok
observableListMethod2(s.flatMapIterable(it -> it).cast(BaseClass.class).toList()); // ok, but yuck!
}
Конечно, есть более чистый способ выполнить то, что я пытаюсь сделать?