Je suis dans une situation très similaire à ce que Steve McConnell a mentionné dans Code Complete. Seulement mon problème est basé sur des véhicules et le Trike se retrouve par la loi dans la catégorie des voitures. Les voitures avaient quatre roues jusqu'à présent. En tout cas, mon domaine est inutilement complexe donc il est facile de rester avec l'exemple des chats ci-dessous.
Soyez méfiant envers les classes qui remplacent une routine et ne font rien à l'intérieur de la routine dérivée. Cela indique généralement une erreur dans la conception de la classe de base. Par exemple, supposez que vous ayez une classe Chat et une routine Griffer() et supposons que vous découvriez finalement que certaines chats sont dégriffés et ne peuvent pas griffer. Vous pourriez être tenté de créer une classe dérivée de Chat appelée ChatSansGriffes et de remplacer la routine Griffer() pour ne rien faire. Cette approche présente plusieurs problèmes :
Cela viole l'abstraction (contrat d'interface) présentée dans la classe Chat en changeant la sémantique de son interface.
Cette approche devient rapidement incontrôlable lorsque vous l'étendez à d'autres classes dérivées. Que se passe-t-il lorsque vous trouvez un chat sans queue ? Ou un chat qui n'attrape pas de souris ? Ou un chat qui ne boit pas de lait ? Vous finirez par avoir des classes dérivées comme ChatSansQueueSansSourisSansLait.
Au fil du temps, cette approche donne lieu à un code confus à maintenir car les interfaces et le comportement des classes ancestrales n'impliquent que peu ou rien sur le comportement de leurs descendants.
L'endroit pour corriger ce problème n'est pas dans la classe de base, mais dans la classe Cat d'origine. Créez une classe Griffes et incluez-la dans la classe Chats. Le problème principal était l'hypothèse que tous les chats griffent, donc corrigez ce problème à la source, plutôt que de simplement le panser à la destination.
Conformément au texte de son excellent livre ci-dessus. Voici ce qui est mauvais
La classe parent n'a pas besoin d'être abstraite
public abstract class Cat {
public void scratch() {
System.out.println("Je peux griffer");
}
}
Classe dérivée
public class ChatSansGriffes extends Cat {
@Override
public void scratch() {
// ne rien faire
}
}
Maintenant, il suggère de créer une autre classe Griffes
, mais je ne comprends pas comment je peux utiliser cette classe pour éviter le besoin de ChatSansGriffes#Griffer
.