Le Liskov Substitution Principle (LSP) indique que le remplacement d'une instance d'une classe de base par une instance d'une classe dérivée doit toujours fonctionner. Ceci est une caractéristique de base de la POO, pas un problème.
Le problème est dans votre modèle - considérons quelle est la relation entre un point 2D et un point 3D. Ayant Point3D
Hériter de Point2D
indique qu'un Point3D
est unPoint2D
, qui est, tous les Point3D
« s sont également Point2D
» s. Mais cela ne correspond pas vraiment à ce que vous modélisez! En mathématiques, seuls les points 3D du plan 2D (ceux avec z == 0
) sont en réalité des points 2D. Cette divergence est la source de cette échappatoire qui pourrait transformer votre Circle
en une sphère.
Le modèle OOP pour cela pourrait en fait être le contraire: tous les points 2D sont points 3D, avec z == 0
. Ainsi, Point2D
héritant de Point3D
aurait un sens. Cela ouvrirait cependant une nouvelle série de problèmes de mutabilité: si vous pouvez accéder à Point2D
en tant que Point3D
et que vous le modifiez, vous pouvez définir ses coordonnées z
comme étant non nulles et se retrouver avec une incohérence Point2D
ce n'est plus réellement 2D. LSP est à nouveau cassé.
Il est tentant de représenter la relation entre 2D et un point 3D en POO dans les deux sens:
- Un point 3D contient une plus coordonnée qu'un point 2D ne pas utiliser, ainsi il devrait être la classe dérivée
... ou ...
- Mathématiquement, un p 2D oints est également un point 3D, donc il devrait être la classe dérivée
... mais la ligne de fond est tout simplement que ni classe peut hériter de l'autre, parce que le LSP est cassé ou l'autre manière . Conservez-les en tant que classes distinctes, pommes avec pommes et Circle
avec Point2D
s, et utilisez d'autres fonctionnalités de langue si vous avez besoin de factoriser le code commun entre les points - la programmation générique, par exemple.
Très clair, merci pour l'explication! Mais je pensais utiliser une super classe abstraite afin de [dry'] (https://en.m.wikipedia.org/wiki/Don%27t_repeat_yourself) ... (Il est maintenant même possible en python avec 'ABC 's aka Abstract Base Classes) La classe abstraite ne peut pas être instanciée,' Point2D' et 'Point3D' ne héritent pas l'un de l'autre, donc le LSP est respecté. Ton opinion? –
Oui, cela serait valide, du moment que vous prenez soin de ne mettre dans la classe de base que des choses qui sont réellement communes aux deux types de points. – Quentin