Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Principio de sustitución de Liskov #45

Open
delapuente opened this issue May 12, 2019 · 0 comments
Open

Principio de sustitución de Liskov #45

delapuente opened this issue May 12, 2019 · 0 comments
Labels
discusión Para compartir opiniones acerca de un tema ejemplo Un caso de uso o fragmento de código visto en clase

Comments

@delapuente
Copy link
Collaborator

delapuente commented May 12, 2019

El otro día en clase, @ramoncorominas planteaba "¿cuando sí se cumple el principio de sustitución de Liskov?". Le puse en clase el ejempo de los múltiples decodificadoes de audio .ogg, .wav, .mp3... donde deberíamos poder sustituir uno por otro... ¡Nada más lejos de la realidad, como apuntaba Ramón! Y es cierto, planteé mal el ejemplo (para empezar porque esas clases serían hermanas, así que no hay herencia entre ellas).

Dejad que lo plantee de otra forma, saltando de lo más formal a lo más divugativo. Formalmente, el principio de sustitución dice:

What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.

Me gustaría que nos fijáramos en este "What is wanted here..." que significa que podemos definit una forma de herencia o especialización (subtyping) definida por poder o no hacer esta sustitución. Tal clase de especialización se llama especialización de comportamiento (behavioral subtyping).

Este es el tipo de especialización que es deseable en un programa. Intuitivamente, porque la cosa va de reutilizar código, que suele estar en los métodos (comportamiento como decía @eun-plata cuando dió su defnición de objeto).

Esto no significa que la noción "un cuadrado es un rectángulo con los lados iguales" sea incorrecta bajo otras definiciones de especialización. Significa que para la definición de Python que hemos dado de un rectángulo:

class Rectangle:

    def __init__(self, w, h):
        self._w = w
        self._h = h

    def set_width(self, w):
        self._w = w

    def set_height(self, h):
        self._h = h

    def area(self):
        return self.w * self.h

Y del cuadrado:

class Square(Rectangle):

    def __init__(self, length):
        self._w = self._h = length

   def set_width(self, w):
        self._w = self._h = w

   def set_height(self, h):
        self._h = self._w = h

Tratar de ver un cuadrado como una especialización de comportamiento de un rectángulo no va a funcionar. El ejemplo venía con la prueba del test:

def test_area(rect):
    rect.set_width(5)
    rect.set_height(4)
    assert rect.area() == 20

Tan pronto como le pase a la función test_area un cuadrado, va a dejar de funcionar, pese a que la función maneja la API del rectángulo como cabe esperar.

La especialización por comportamiento permite la reutilización del código en la guisa todo o nada. Si en la clase derivada te sobran métodos, es mejor optar
por la composición:

class Cuadrado:

    def __init__(self, l):
        self._rectangle = Rectangle(l, l)

    def set_length(self, l):
        self._rectangle.set_width(l)
        self._rectangle.set_height(l)

    def area(self):
        return self._rectangle.area()

@ramoncorominas, un ejemplo de "buena herencia" son aquellas clases que expanden capacidades. Por ejemplo, un rectángulo coloreado:

class ColoredRectangle(Rectangle):

    def __init__(self, w, h, color):
        super().__init__(w, h)
        self.color = color

    def paint(self):
        print(f'Draw a square of {self.color} color')
@delapuente delapuente added discusión Para compartir opiniones acerca de un tema ejemplo Un caso de uso o fragmento de código visto en clase labels May 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discusión Para compartir opiniones acerca de un tema ejemplo Un caso de uso o fragmento de código visto en clase
Projects
None yet
Development

No branches or pull requests

1 participant