Considérez que j'ai l'interface suivante:
public interface A { public void b(); }
Cependant, je veux que chacune des classes qui l'implémentent ait un type de retour différent pour la méthode b ().
Exemples:
public class C {
public C b() {}
}
public class D {
public D b() {}
}
Comment définirais-je mon interface pour que cela soit possible?
Si le type de retour doit être le type de la classe qui implémente l'interface, alors ce que vous voulez s'appelle un type F-bounded :
public interface A<T extends A<T>>{ public T b(); }
public class C implements A<C>{
public C b() { ... }
}
public class D implements A<D>{
public D b() { ... }
}
En mots, A
déclare un paramètre de type T
qui prendra la valeur de chaque type concret qui implémente A
. Ceci est généralement utilisé pour déclarer des méthodes comme clone()
ou copy()
qui sont bien typées. Comme autre exemple, il est utilisé par Java.lang.Enum
pour déclarer que la méthode héritée de chaque énumération compareTo(E)
s'applique uniquement aux autres énumérations de ce type particulier.
Si vous utilisez ce modèle assez souvent, vous rencontrerez des scénarios où vous aurez besoin que this
soit de type T
. À première vue, il peut sembler évident qu'il1, mais vous devrez en fait déclarer une méthode abstract T getThis()
que les implémenteurs devront implémenter trivialement comme return this
.
[1] Comme les commentateurs l'ont souligné, il est possible de faire quelque chose de sournois comme X implements A<Y>
Si X
et Y
coopèrent correctement. La présence d'une méthode T getThis()
montre encore plus clairement que X
contourne les intentions de l'auteur de l'interface A
.
Génériques.
public interface A<E>{
public E b();
}
public class C implements A<C>{
public C b(){
return new C();
}
}
public class D implements A<D>{
public D b(){
return new D();
}
}
Recherchez des génériques pour plus de détails, mais (très) fondamentalement, ce qui se passe, c'est que A
laisse le type de E
aux classes d'implémentation (C
et D
).
Donc, fondamentalement, A ne sait pas (et n'a pas besoin de savoir) ce que pourrait être E dans une implémentation donnée.
Puisque Java prend en charge les types de retour covariants (puisque Java 1.5)), vous pouvez faire:
public interface A { public Object b(); }