Principe de substitution
Nous avons vu différents types d'abstraction, et nous allons nous intéresser à l'abstraction par hiérarchie de type, qui est un des piliers des concepts de l'orienté-objet.
Hiérarchie de classe, héritage
En orienté-objet, l'héritage permet par exemple de définir des comportements minimum pour une classe, et d'ajouter les comportements spécifiques dans des classes enfants, qui héritent (dérivent) de la classe parent.
Parmi les avantages de cette manière de programmer, nous pouvons retenir qu'il n'est plus nécessaire de re-définir dans les classes enfants ce qui est déjà défini dans les classes parents. Ceci nous permet une abstraction par hiérarchie de type, c'est à dire que nous pouvons considérer les différents enfants comme étant du type parent.
Un des exemple souvent utilisé pour expliquer l'héritage est issu de la géométrie :
- Un quadrilatère possède 4 côtés
- Un parallélogramme possède aussi 4 côtés, c'est un quadrilatère.
Il est cependant particulier, car il possède en plus la particularité d'avoir des côtés opposés de même longueur.- Un rectangle possède aussi 4 côtés et des côtés opposés de même longueur, c'est un quadrilatère, et même un parallélogramme.
Il est cependant particulier, car il possède en plus la particularité d'avoir 4 angles droits.- Un carré possède toutes les caractéristiques d'un rectangle, c'est donc un rectangle.
Il est cependant particulier, car il possède en plus la particularité d'avoir 4 côtés de même longueur.
- Un carré possède toutes les caractéristiques d'un rectangle, c'est donc un rectangle.
- Un rectangle possède aussi 4 côtés et des côtés opposés de même longueur, c'est un quadrilatère, et même un parallélogramme.
- Un parallélogramme possède aussi 4 côtés, c'est un quadrilatère.
Ce type de classement est tout à fait correct au niveau de la sémantique et selon le point de vue de la géométrie, et naturellement c'est de cette manière que nous construisons notre hiérarchie de classes en programmation.
Cependant, Liskov soulève un problème au niveau du comportement attendu, car notre structure renforce à chaque fois les contraintes nécessaires à la création d'une forme par rapport à sa forme parent.
Principe de substitution, en bref
“Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.”
« Si q(x) est une propriété démontrable pour tout objet x de type T, alors q(y) est vraie pour tout objet y de type S tel que S est un sous-type de T. »
Barbara Liskov2et Jeannette Wing3Sémantique et substitution de Liskov
La sémantique nous pousse à utiliser une hiérarchie comme nous l'avons vu dans notre exemple du carré qui hérite des propriétés du rectangle, ce qui est logique car un carré est au moins un rectangle.
Cependant, si nous définissons dans la classe rectangle les méthodes suivantes affecteLargeur(entier largeur), affecteHauteur(entier hauteur), et entier donneSurface(), la méthode de calcul de la surface renvera la largeur multipliée par la hauteur. C'est correct.
Selon Liskov, le carré doit pouvoir à tout moment se comporter comme un rectangle. Notre exemple semble fonctionner correctement, voyons un cas pratique...
- L'utilisateur crée un rectangle r et carré c.
- Il décide de leur affecter une largeur égale à 2. Le carré, sachant que ses 4 côtés sont égaux, en profite pour affecter une hauteur identique.
- Il décide ensuite de leur affecter une hauteur égale à 3. Le carré, sachant que ses 4 côtés sont égaux, en profite pour affecter une largeur identique.
- L'utilisateur demande ensuite la surface du rectangle, et la méthode lui renvoie 6, ce qui est correct.
- Il demande ensuite la surface du carré, et selon Liskov le résultat attendu est identique à celui du rectangle (6). Cependant, le résultat pour le carré est différent (9).
Que s'est-il passé ? La méthode donne surface s'est comportée exactement de la méme manière pour le carré que pour le rectangle (largeur*hauteur), mais nous violons le principe de substitution de Liskov à chaque fois que nous affectons une valeur pour la largeur ou la hauteur du carré, car cela provoque un résultat différent.
Pourtant nous sommes obligés dans les affectations du carré d'afecter la méme valeur à la largeur et à la hauteur, sinon nous ne respectons plus la sémantique du carré.
Héritage et substitution de Liskov
Un des moyens de respecter les principes de substitutions de Liskov est d'inverser notre conçeption habituelle de l'héritage, et de coder un rectangle qui hérite d'un carré.
Proposition de solution
Nous pouvons donc utiliser la solution suivante : comme notre carré ne peut pas produire le résultat attendu sur un rectangle, nous ne définirons pas le carré comme héritant du rectangle, mais tous deux sont au même niveau, héritant du quadrilatère.
« Heu... Comment je fais si je veux mettre ensemble les carrés et les rectangles ? »
Comme le carré et le rectangle possèdent des caractéristiques communes que ne partagent pas les autres quadrilatères (4 angles droits), nous pouvons dire que le carré et le rectangle implémentent l'interface "QuatreAnglesDroits".
Par exemple en Java, si nous demandons sur notre objet qui est de type réel carré ou rectangle s'il est une instance de "Quadrilatère", il nous répondra "oui", et de la même manière si nous lui demandons s'il est une instance de "QuatreAnglesDroits" il nous répondra aussi "oui".
Spécifications et substitution de Liskov
L'abstraction par spécifications nous donne quelques pistes pour respecter le principe de substitution de Liskov :
- La clause REQUIRES dans le sous-type doit être égale ou inférieure à celle du type parent : affaiblissement des pré-conditions.
- La clause EFFECTS dans le sous-type doit produire au moins le même résultat que celle du type parent : renforcement des post-conditions.
Remarque
Même si je n'adhère pas toujours aux propos de Barbara Liskov4, les principes de substitution de Liskov soulèvent certaines questions intéressantes, et nous sensibilisent à certains dangers dans notre pratique de l'orienté-objet.
Nous devons avoir conscience du problème, mais nous utilisons souvent les principes d'héritage sans modifier le comportement des sous-classes, ce qui est sans danger.
Je n'ai pas le temps pour l'instant de détailler plus le sujet, mais il mérite que l'on s'y attarde, et je le ferais par la suite.
Deutsche Übersetzung
Sie haben gebeten, diese Seite auf Deutsch zu besuchen. Momentan ist nur die Oberfläche übersetzt, aber noch nicht der gesamte Inhalt.Wenn Sie mir bei Übersetzungen helfen wollen, ist Ihr Beitrag willkommen. Alles, was Sie tun müssen, ist, sich auf der Website zu registrieren und mir eine Nachricht zu schicken, in der Sie gebeten werden, Sie der Gruppe der Übersetzer hinzuzufügen, die Ihnen die Möglichkeit gibt, die gewünschten Seiten zu übersetzen. Ein Link am Ende jeder übersetzten Seite zeigt an, dass Sie der Übersetzer sind und einen Link zu Ihrem Profil haben.
Vielen Dank im Voraus.
Dokument erstellt 03/01/2010, zuletzt geändert 26/10/2018
Quelle des gedruckten Dokuments:https://www.gaudry.be/de/oriente-objet-principe-substitution.html
Die Infobro ist eine persönliche Seite, deren Inhalt in meiner alleinigen Verantwortung liegt. Der Text ist unter der CreativeCommons-Lizenz (BY-NC-SA) verfügbar. Weitere Informationen auf die Nutzungsbedingungen und dem Autor.
- ↑ Barbara Liskov : Barbara Liskov (7-11-1939) est professeur au MIT [Massachusetts Institute of Technology] au département Engineering's Electrical Engineering and Computer Science.
- ↑ Jeannette M. Wing : Jeannette M. Wing, a fait ses études au MIT [Massachusetts Institute of Technology], et est professeur d'informatique à l'Université Carnegie Mellon. Elle est directrice du département d'informatique.
- ↑ Liskov et equals : Barbara Liskov considère que l'implémentation de la méthode equals retourne true, pour des objets mutables, uniquement lors d'une égalité de pointeur (l'opérateur ==). Son argumentation est tout à fait justifiée, mais sa solution n'est absolument pas acceptable, car Java se base sur cette méthode (parfois en corrélation avec hashCode) pour l'égalité de deux objets au niveau de la logique métier, par exemple dans les collections.
Referenzen
- La maîtrise du développement du logiciel : abstraction et spécification : Barbara Liskov et John V. Guttag (1990)
- The Liskov Substitution Principle : T. S. Norvell (2003)
Diese Verweise und Links verweisen auf Dokumente, die während des Schreibens dieser Seite konsultiert wurden, oder die zusätzliche Informationen liefern können, aber die Autoren dieser Quellen können nicht für den Inhalt dieser Seite verantwortlich gemacht werden.
Der Autor Diese Website ist allein dafür verantwortlich, wie die verschiedenen Konzepte und Freiheiten, die mit den Nachschlagewerken gemacht werden, hier dargestellt werden. Denken Sie daran, dass Sie mehrere Quellinformationen austauschen müssen, um das Risiko von Fehlern zu reduzieren.