¿Cómo el fortalecimiento de las condiciones previas y el debilitamiento de las condiciones posteriores violan el principio de sustitución de Liskov?

19

Leí que el principio de sustitución de Liskov se viola si:

  1. Las condiciones previas se fortalecen, o

  2. Las condiciones posteriores se debilitan

Pero todavía no entiendo completamente cómo estos dos puntos violarían el principio de sustitución de Liskov. ¿Puede alguien explicarme con un ejemplo? Específicamente, ¿cómo una de las condiciones anteriores causaría una situación en la que un objeto de subclase no puede ser sustituido por un objeto de superclase?

Friki
fuente

Respuestas:

29
  1. Suponga que su clase base funciona con un miembro int. Ahora su subtipo requiere que int sea positivo. Esto se refuerza las condiciones previas, y ahora cualquier código que funcionó perfectamente bien antes con entradas negativas está roto.

  2. Del mismo modo, asuma el mismo escenario, pero la clase base solía garantizar que el miembro sería positivo después de ser llamado. Luego, el subtipo cambia el comportamiento para permitir entradas negativas. El código que funciona en el objeto (y supone que la condición posterior es un int positivo) ahora está roto ya que la condición posterior no se confirma.

Estos son, por supuesto, ejemplos triviales, pero el concepto se mantiene. Cosas como dejar abierta una conexión de archivo / base de datos es un ejemplo de una condición posterior facilitada que genera problemas.

Telastyn
fuente
1

ingrese la descripción de la imagen aquí

Invariante: plantilla de SelfDrivingVehicle que permanece sin cambios en todos los subtipos, es decir, el orden en el que ejecuta los comportamientos anulados para llegar al destino.

Asumamos un método más aquí

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

Precondición: SelfDriveVehicle, el Tipo base no tiene vehículos (aquí el contexto es Agregar) y está en Precondición debilitada que no puede ser alterada por ninguno de sus subtipos cambiando los vehículos de propiedad y Fortaleciéndolo explícitamente. Cualquiera de los subtipos solo puede invocar Agregar.

Condición posterior: una vez que se invoca Agregar, el tipo base está en una condición posterior fortalecida que no puede debilitarse mediante subtipos al alterar el valor de los vehículos.

El estado del tipo base vuelve a su estado original una vez que se invoca Agregar comportamiento.

Vishal Patwardhan
fuente
-1

Este ejemplo es bastante golpeado hasta la muerte, pero considere la posibilidad de Cuadrado / Rectángulo o Círculo / Elipse. Supongamos que tiene un rectángulo de clase base que define un objeto con una longitud y un ancho. Si tiene una clase Square que hereda la clase Rectangle, tendría una regla en su setter / getter que requeriría que cualquier cambio en la longitud o el ancho altere su contraparte. Estos requisitos dimensionales fortalecen las precondiciones porque a un rectángulo sustituido por un cuadrado le faltarían estos requisitos dimensionales. Suponga que invierte la herencia para que un Rectángulo herede un Cuadrado, estaría debilitando las condiciones de la publicación al relajar los requisitos dimensionales para permitir que el Rectángulo se comporte de forma independiente.

Sin embargo, si eliminara la capacidad de cambio dimensional, el principio de sustitución se cumple porque si ni un Rectángulo ni un Cuadrado pueden cambiar las dimensiones, entonces tienen las mismas condiciones previas y posteriores independientemente de la herencia. Ambos tienen una longitud, ambos tienen un ancho y ninguno puede alterar esos valores.

ref: Wikipedia - http://en.wikipedia.org/wiki/Liskov_substitution_principle

Joel Etherton
fuente
1
Lamentablemente, ese ejemplo no tiene nada que ver con la verificación formal. No hay contratos
Frank Hileman