J'ai une classe de base, Base. Il a deux sous-classes, Sub1et Sub2. Chaque sous-classe a quelques méthodes supplémentaires. Par exemple, Sub1a Sandwich makeASandwich(Ingredients... ingredients)et Sub2a boolean contactAliens(Frequency onFrequency).
Puisque ces méthodes prennent des paramètres différents et font des choses complètement différentes, elles sont complètement incompatibles et je ne peux pas simplement utiliser le polymorphisme pour résoudre ce problème.
Basefournit la plupart des fonctionnalités, et j'ai une grande collection d' Baseobjets. Cependant, tous les Baseobjets sont soit un, Sub1soit un Sub2et parfois j'ai besoin de savoir qui ils sont.
Cela semble être une mauvaise idée de faire ce qui suit:
for (Base base : bases) {
if (base instanceof Sub1) {
((Sub1) base).makeASandwich(getRandomIngredients());
// ... etc.
} else { // must be Sub2
((Sub2) base).contactAliens(getFrequency());
// ... etc.
}
}
Donc, je suis venu avec une stratégie pour éviter cela sans casting. Basea maintenant ces méthodes:
boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();
Et bien sûr, Sub1implémente ces méthodes comme
boolean isSub1() { return true; }
Sub1 asSub1(); { return this; }
Sub2 asSub2(); { throw new IllegalStateException(); }
Et les Sub2met en œuvre dans le sens opposé.
Malheureusement, maintenant Sub1et Sub2ont ces méthodes dans leur propre API. Donc, je peux le faire, par exemple, sur Sub1.
/** no need to use this if object is known to be Sub1 */
@Deprecated
boolean isSub1() { return true; }
/** no need to use this if object is known to be Sub1 */
@Deprecated
Sub1 asSub1(); { return this; }
/** no need to use this if object is known to be Sub1 */
@Deprecated
Sub2 asSub2(); { throw new IllegalStateException(); }
De cette façon, si l'objet est connu pour être seulement un Base, ces méthodes sont non dépréciées et peuvent être utilisées pour se "convertir" en un type différent afin que je puisse invoquer les méthodes de la sous-classe. Cela me semble élégant d’une certaine manière, mais d’un autre côté, j’abuse un peu des annotations obsolètes comme moyen de "supprimer" des méthodes d’une classe.
Puisqu'une Sub1instance est vraiment une base, il est logique d'utiliser l'héritage plutôt que l'encapsulation. Est-ce que je fais bien? Existe-t-il un meilleur moyen de résoudre ce problème?
instanceof, d'une manière qui nécessite beaucoup de dactylographie, est source d'erreurs et rend difficile l'ajout de plusieurs sous-classes.
Sub1et Sub2ne peuvent pas être utilisés de manière interchangeable, alors pourquoi les traitez-vous comme tels? Pourquoi ne pas garder une trace de vos "sandwich-makers" et de vos "alien-contacters" séparément?