Avertissement: Cette question contient du code en utilisant la bibliothèque rxjava
, mais le problème n'est pas lié à celle-ci. Je fournis toutes les informations nécessaires pour permettre à ceux qui ne sont pas familiers avec cette bibliothèque de répondre.Impossible de passer la classe interne d'une sous-classe générique en utilisant un caractère générique délimité
je la méthode suivante qui sélectionne une source de données basée sur si certaines données sont mises en cache ou non:
public Observable<? extends MetricDataSource> createForOwners() {
return Observable.defer(new Func0<Observable<? extends MetricDataSource>>() {
@Override
public Observable<? extends MetricDataSource> call() {
if (ownersCache.isCached()) {
return cacheMetricDataSource;
} else {
return androidApiMetricDataSource;
}
}
});
}
Il ne peut pas compiler avec l'erreur suivante:
Error:(29, 26) error: method defer in class Observable<T#2> cannot be applied to given types;
required: Func0<Observable<T#1>>
found: <anonymous Func0<Observable<? extends MetricDataSource>>>
reason: cannot infer type-variable(s) T#1
(argument mismatch; <anonymous Func0<Observable<? extends MetricDataSource>>> cannot be converted to Func0<Observable<T#1>>)
where T#1,T#2 are type-variables:
T#1 extends Object declared in method <T#1>defer(Func0<Observable<T#1>>)
T#2 extends Object declared in class Observable
La signature de Observable.defer
est:
public final static <T> Observable<T> defer(Func0<Observable<T>> observableFactory)
Func0
essentiellement co ntains une méthode call()
qui renvoie un objet du type générique:
public interface Func0<T> { T call(); }
Les sources de données sont déclarées comme:
private final Observable<AndroidApiMetricDataSource> androidApiMetricDataSource;
private final Observable<CacheMetricDataSource> cacheMetricDataSource;
Alors, pourquoi il échoue? defer
attend un Observable<T>
et je lui donne un Observable<? extends MetricDataSource>
, qui devrait bien entrer dans ce T
.
Modifier: Si je remplace la méthode defer
par un privé dans la classe actuelle puis remplacer Observable<T>
-T
à la fois l'argument et le type de retour, il compile. Cependant, je dois utiliser la méthode originale Observable
.
Ainsi, de cette façon il échoue:
private static <T> Observable<T> defer(Func0<Observable<T>> observableFactory) {
return null;
}
Et celui-ci compile:
private static <T> T defer(Func0<T> observableFactory) {
return null;
}
mon écriture sur joker - [wildcard hell] (http://bayou.io/draft/Capturing_Wildcards.html#Wildcard_Hell), [wildcard manquant] (http://bayou.io/draft/Wildcard_Case_Studies.html#Missing_Wildcards) – ZhongYu
Réponse très utile, même si je l'ai déjà résolu autrement (voir ma réponse). J'ai une question sur votre réponse. La distribution fonctionne si je l'entoure d'une méthode similaire à votre exemple 'vary()' sur le second lien. Il émet uniquement un avertissement de distribution non contrôlée. Mais si j'essaie la distribution directement sans la méthode, elle ne compile pas avec une erreur 'Incompatible types'. Pourquoi, s'il fait la même chose? –
oui, votre solution fonctionne (mais alors peut-être que ça va bomber à des problèmes aussi et nécessiter un casting). voir [casting entre les types concrets] (http://bayou.io/draft/Wildcard_Case_Studies.html#Casting_Between_Concrete_Types) – ZhongYu