El principio de sustitucion de Liskov tiene dos formas de formularse: la enrevesada y la de andar por casa. Yo voy a anunciar la de andar por casa, pero aquí vamos a entender la formal, formulada por Barbara Liskov en 1988.
La definición más fácil de manejar es la siguiente: “los objetos a los que hace referencia un programa deberían ser sustituibles por sus subtipos sin alterar el buen funcionamiento del programa”.
Personalmente me considero un tiquismiquis de las definiciones formales y matemáticas, así que vamos a ver la que enunció Liskov. Estoy completamente seguro de que si existe alguna duda con la definicion informal quedará aclarada.
Si por cada objeto de tipo o1 de tipo S hay un objeto o2 de tipo T, para todos los procedimientos P definidos en términos de T, si el comportamiento de P no varía cuando o1 es sustituido por o2, entonces S es un subtipo de T.
Lee atentamente la definición anterior. Si traducimos esto a código, lo que nos dice es algo como “si un método usa como parámetro un objeto de tipo T y se puede cambiar por otro objeto de tipo S sin alterar el buen funcionamiento del método, entonces S es un subtipo de T”.
Donde mejor se puede ver esto es en un método que usa una interfaz como parámetro. Efectivamente podríamos cambiar la firma del método por un parámetro que sea de un tipo concreto que use la interfaz, aunque violaríamos otros principios.
En última instancia lo que nos quiere decir el principio de sustitucion de Liskov es lo mismo de siempre: programa sobre interfaces de forma que el cliente no sepa qué objeto concreto está usando. ¡Polimorfismo!
El problema Cuadrado-Rectangulo
Siguiendo con el ejemplo del libro Arquitectura Limpia de Robert C. Martin que se está siguiendo para ilustrar estos principios SOLID, veamos un caso en el que se vulnera el LSP.
Podríamos pensar que un rectángulo es la generalizacion de un cuadrado, pero hacer eso incumpliría el principio de Liskov, pues un cuadrado no tiene los mismos métodos que un rectángulo y no son sustituibles en el método de Main.
La solucion propuesta en el libro que mantenemos como guía es la creacion de una sentencia de control que nos permita saber si estamos ante un rectángulo o un cuadrado en tiempo de ejecución. A mi no me gusta la solucion. Sinceramente prefiero que ambas figuras sean concreciones de la familia de los paralelogramos y, mediante una factoría se construyan estas figuras pasando parámetros como el alto, ancho y el angulo menos que formen sus lados. A fin de cuentas, tendríamos el mismo problema con los rombos y romboides. De esta forma mantenemos la coherencia geométrica y cumplimos el principio de Liskov.
Ahora lee la definición informal del comienzo.