C'est un côté du problème de la covariance. Voir par exemple Covariance and contravariance. Et Demonstrate covariance and contravariance in Java?. Ce n'est pas vraiment là où Java excelle, mais il y a quelques options. Tout d'abord, lors de la substitution d'une méthode, vous êtes autorisé à déclarer un type de retour plus spécifique. Par exemple, en MySubClass
vous pouvez déclarer:
@Override
public MySubClass filterOn(String something) {
// ...
}
Maintenant, cela ne résout pas votre problème. Vous avez toujours besoin d'un moyen pour que cette méthode crée et fasse quelque chose à un objet MySubClass
. Ce qu'il fait, il libère le code client d'avoir besoin d'un casting du tout. Vous pouvez prendre la mise en œuvre de la méthode sous forme de réponse de davidxxx (à condition que result.doSomethingUsingThisInstance()
est protected
ou public
):
@Override
public MySubClass filterOn(String something) {
MySubClass result = new MySubClass();
result.doSomethingUsingThisInstance(this, something);
return result;
}
Vous pouvez être ennuyé d'avoir à dupliquer cette méthode dans tout ce que vous sous-classes. Si le vrai travail reste dans result.doSomethingUsingThisInstance()
je devrais penser que vous pourriez être en mesure de vivre avec.
L'autre idée est de clone()
pour produire un objet du type d'exécution correcte:
public class MyClass implements Cloneable {
public MyClass filterOn(String something) {
try {
MyClass result = (MyClass) this.clone();
result.doSomethingUsingThisInstance(this, something);
return result;
} catch (CloneNotSupportedException cnse) {
throw new AssertionError(cnse);
}
}
}
je penserais deux fois avant d'utiliser cette idée, cependant. L'une des raisons pour lesquelles votre clone contient des données que vous ne souhaitez pas utiliser, vous devrez peut-être vous assurer qu'il est effacé avant de travailler sur le clone. Vous pouvez toujours le combiner avec le retour du sous-type spécifique dans la sous-classe, maintenant il faut juste un casting (encore dans la mise en œuvre, rien que le client a besoin de se soucier):
public class MySubClass extends MyClass {
@Override
public MySubClass filterOn(String something) {
return (MySubClass) super.filterOn(something);
}
}
La valeur de retour de 'filterOn' est' MyClass', pas 'MySubClass', donc l'exception est suffisamment valide. Changez le type de 'result' pour le réparer. – Henrik
'MyClass result = new MyClass();' dans votre méthode de filtrage a un problème. vous créez super instance, et retourné à la fin, vous ne pouvez pas le transformer en sous-type. Je suppose que vous voudrez peut-être remplacer la méthode filterOn dans MySubClass. – Kent
La solution la plus simple serait de ne pas lancer subClass2 car ce n'est pas une intuition MySubClass. Si vous avez besoin d'une instance de 'MySubClass', remplacez simplement' filteron' et renvoyez une instance 'MySubClass' à la place. – n247s