Comment le renforcement des conditions préalables et l'affaiblissement des post-conditions violent-ils le principe de substitution de Liskov?

19

J'ai lu que le principe de substitution de Liskov est violé si:

  1. Les conditions préalables sont renforcées, ou

  2. Les postconditions sont affaiblies

Mais je ne sais pas encore comment ces deux points violeraient le principe de substitution de Liskov. Quelqu'un peut-il expliquer avec un exemple. Plus précisément, comment l'une des conditions ci-dessus entraînerait-elle une situation dans laquelle un objet de sous-classe ne peut pas être substitué à un objet de super-classe?

Geek
la source

Réponses:

29
  1. Supposons que votre classe de base fonctionne avec un membre int. Maintenant, votre sous-type nécessite que int soit positif. Ceci est des conditions préalables renforcées, et maintenant tout code qui fonctionnait parfaitement bien avant avec des entrées négatives est cassé.

  2. De même, supposez le même scénario, mais la classe de base utilisée pour garantir que le membre sera positif après avoir été appelé. Le sous-type modifie ensuite le comportement pour autoriser les entrées négatives. Le code qui fonctionne sur l'objet (et suppose que la post-condition est un entier positif) est maintenant rompu car la post-condition n'est pas respectée.

Ce sont bien sûr des exemples triviaux, mais le concept tient. Des choses comme laisser une connexion de fichier / base de données ouverte est un exemple de post-condition allégée qui mène à des problèmes.

Telastyn
la source
1

entrez la description de l'image ici

Invariant - Modèle de SelfDrivingVehicle qui reste inchangé dans tous les sous-types, c'est-à-dire l'ordre dans lequel il exécute les comportements substitués pour atteindre la destination.

Supposons une autre méthode ici

           -List<SelfDrivingVehicle> vehicles 
           +Add(SelfDrivingVehicle vehicle)
            vehicles.add(vehicle)

Condition préalable - SelfDriveVehicle le type de base ne contient aucun véhicule (ici, le contexte est Ajouter) et sa condition préalable affaiblie qui ne peut être modifiée par aucun de ses sous-types en modifiant les véhicules de propriété et en le renforçant explicitement. N'importe lequel des sous-types peut uniquement appeler Add.

Postcondition - Une fois que Add est invoqué, le type de base est en postcondition renforcée qui ne peut pas être affaiblie par des sous-types en modifiant la valeur des véhicules.

L'état du type de base revient à son état d'origine une fois que le comportement d'ajout est invoqué.

Vishal Patwardhan
la source
-1

Cet exemple est à peu près battu à mort, mais considérez la possibilité Carré / Rectangle ou Cercle / Ellipse. Supposons que vous ayez une classe de base Rectangle qui définit un objet avec une longueur et une largeur. Si vous avez une classe Square qui hérite de la classe Rectangle, elle aurait une règle dans son setter / getter qui exigerait que tout changement de longueur ou de largeur modifie son homologue. Ces exigences dimensionnelles renforcent les conditions préalables car un rectangle substitué à un carré n'aurait pas ces exigences dimensionnelles. Supposons que vous inversiez l'héritage pour qu'un rectangle hérite d'un carré, vous affaibliriez les conditions de publication en assouplissant les exigences dimensionnelles pour permettre au rectangle de se comporter indépendamment.

Cependant, si vous supprimez la capacité de changement dimensionnel, le principe de substitution est valable car si ni un rectangle ni un carré ne peuvent changer de dimension, alors ils ont des conditions de pré et de post égales indépendamment de l'héritage. Les deux ont une longueur, les deux ont une largeur et aucun ne peut modifier ces valeurs.

réf: Wikipedia - http://en.wikipedia.org/wiki/Liskov_substitution_principle

Joel Etherton
la source
1
Malheureusement, cet exemple n'a rien à voir avec une vérification formelle. Il n'y a pas de contrats.
Frank Hileman