23 votes

Limites des sous-classes OOP

En java, quelle est la bonne façon de concevoir une sous-classe qui réduit la fonctionnalité de la super-classe ?

Par exemple, considérons la classe "Man", qui possède la fonction "See" et la sous-classe "BlindMan" qui ne devrait pas avoir cette fonction, mais devrait avoir tout le reste que "Man" possède.

La seule solution que j'ai trouvée est d'avoir une classe abstraite "Man", et deux sous-classes "SeeingMan" et "BlindMan", avec SeeinMan ajoutant une fonction "See".

Cependant, le problème avec cette solution est que si je veux maintenant ajouter une classe "DeafMan", qu'est-ce qu'elle étend ? SeeingMan ? et que se passe-t-il si cet homme est à la fois sourd et aveugle ?

14voto

Dory Zidon Points 3069

Je pense que vous devriez utiliser la composition plutôt que l'héritage dans ce cas, ou avoir plusieurs sous-classes qui composent l'humain.

Bien que je comprenne votre logique, une BaseClass est un contrat, qui garantit que toutes les classes de ce type doivent adhérer à ce comportement, avoir une sous-classe qui supprime la méthode parent est un grand NON NON .

Bien que vous puissiez lancer diverses exceptions, je ne m'engagerais pas du tout dans cette voie. Pensez-y de cette façon, disons que je suis un développeur qui a seulement besoin d'accéder à l'objet humain, je m'attends à un certain comportement, et tout d'un coup j'appelle une méthode d'interface et j'obtiens une exception juste parce que je l'ai appelée ? Vous ne devriez pas être au courant des implémentations des classes dérivées et quand vous pouvez ou ne pouvez pas les appeler.

Voici quelques solutions :

Faire de l'humain une composition de BasicHumanFunctions, VisionSystem, etc. Alors l'aveugle n'aurait que quelques-unes de ces fonctions.

class Human {
  private BasicHumanFunctions _basicFunctions; //contains breathe funcitonality.
  private VisionSystem _vision; //contains see
}

class BlindMan {
   private BasicHumanFunctions _basicFunctions;
}

Faites en sorte que la classe de base Human ne contienne que le même comportement que tous les humains, comme la respiration, etc., puis créez un HealthyHuman et un BlindHuman, etc. Vous pouvez ensuite utiliser HealthHuman et le sous-classer davantage si nécessaire.

class Human {
   void breathe() {};
   // other Human basic functions;
} 

class HealthyHuman extends Human {
   void see() {};
   //other healthy human functions
}

class BlindHuman extends Human {
  void useCane() {};
}

Dans le second cas, vous pouvez également utiliser la composition pour partager le comportement :

class BlindHuman extends Human {
   private VoiceSubsystem _voice = new VoiceSybsystem();
   void speaker() {  _voice.speaker();}
}

8voto

informatimago Points 101

Le principe le plus important est le principe de substitution de Lyskov.

Une fois que vous l'avez compris et que vous l'avez appliqué, vous pouvez construire votre modèle comme vous le souhaitez.

Par exemple, on pourrait dire qu'un aveugle voit toujours, mais qu'il ne voit que des images noires (ou grises). Il y a aussi la question des aveugles légaux : vous voulez qu'ils voient quand même quelque chose si l'image est floue ou partielle.

On pourrait aussi dire que l'action que peut faire l'objet n'est pas de voir. Ce que nous faisons, c'est regarder. Voir est le résultat (réussi) de l'observation. Même avec des yeux qui fonctionnent, vous pouvez regarder sans rien voir ! Et les aveugles peuvent toujours "voir" quelque chose sans yeux, ou avec des yeux non fonctionnels, en écoutant (donc en entendant, et en construisant une "image" mentale).

Donc, oubliez les mots "voir" et "entendre". Utilisez "regarder" et "écouter". Et n'attendez rien de tout cela. (vastes conditions préalables).

4voto

Allez-y pour Interfaces .

Définir l'interface pour CommonMan qui a des propriétés communes et utiliser des interfaces individuelles pour des sous-classes distinctes qui ont leurs méthodes spécifiques, alors vous pouvez obtenir les deux méthodes de l'interface.

Exemple :

public class SpecificMan extends CommonMan implements specifiManInter

{

//methods of CommonMan

//Methods of SpecificMan 

}

Classe CommonMan :

public class CommonMan implements CommonManInter {

 //methods of CommonMan

}

4voto

Bob Horn Points 8989

Dory a raison de privilégier la composition à l'héritage. Votre question/problème est à peu près le même que celui du poisson volant. Dans cet exemple, comment gérer une créature qui peut voler ? et nager ?

enter image description here

Il serait maladroit de faire entrer FlyingFish dans la hiérarchie de l'héritage. Au lieu d'essayer d'y parvenir, utilisez la puissance de la composition :

enter image description here

Maintenant, chacune des classes concrètes peut spécifier son comportement. Et c'est l'endroit approprié pour le faire, selon le principe de l'expert en information : L'Expert en Information conduira à placer la responsabilité sur la classe ayant le plus d'informations nécessaires pour la remplir. .

Remarque : il est difficile de lire les avantages à partir de la capture d'écran ci-dessus, aussi les voici à nouveau :

Avantages
- Favoriser la composition d'objets plutôt que l'héritage
- Oblige le développeur à prendre une décision consciente sur le comportement lors du codage (par opposition à la création d'implémentations par défaut dans la classe de base que le développeur doit se rappeler de remplacer).
- En abstrayant le comportement variable, il est maintenant disponible pour être utilisé par d'autres clients.
- Un couplage plus lâche signifie qu'il est plus facile d'adhérer au principe ouvert/fermé, selon lequel le code doit être ouvert à l'extension mais fermé à la modification.

1voto

Patashu Points 14053

Dans la classe Man, ajoutez hasEyes qui est vrai par défaut, et dans BlindMan la rendre fausse par défaut (ou faire des hommes aveugles des instanciations de l'Homme qui se font voler les yeux immédiatement après, par exemple une BlindManFactory ). Ensuite, dans l'histoire de l'homme See codez-le de sorte que s'il n'a pas d'yeux, il échoue automatiquement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X