You are on page 1of 18

Principio de substitucin

de Liskov
(LSP)

Liskov Substitution
Principle
Sub

Super
Donde quiera que se usaba la
superclase, se puede usar la
subclase

Como fue enunciado en 1988

Methods that use references to the


base classes must be able to use the
objects of the derived classes without
knowing it

Extender una clase...

Significa especializarla, aadirle atributos,


hacer ms especfico su comportamiento,
aadir mtodos, sobreponer (overriding)
mtodos respetando la firma precisa,
sobrecargar (overloading) mtodos
especializando el servicio.

As que...
Para respetar el LSP:
La subclase no puede prohibir algo que se permita en
la superclase.
Los mtodos de la subclase deben entregar el mismo
tipo (o uno derivado) como resultados.
Los mtodos de la subclase deben recibir el mismo tipo
(o uno derivado) de parmetros.
Donde quiera que se usaba una referencia a un objeto
de la superclase, se debe poder usar una a un objeto
de la subclase y todo debe funcionar igual.

Ejemplo: Ave

class Ave {
public void volar(){}
public void comer(){}
}

Ejemplo: subclases
class Cuervo extends Ave {}
class Guajolote extends Ave {
volar(){
throw new
UnsupportedOperationException();
}
}

Ejemplo: prueba main


public AveTest {
public static void main(String[] args){
List<Ave> aves = new ArrayList<Ave>();
aves.add(new Ave());
aves.add(new Cuervo());
aves.add(new Guajolote());
hagamosQueVuelen(aves);
}

Ejemplo: prueba
hagamosQueVuelen
static void hagamosQueVuelen(List<Ave>
lstaves){
for (Ave pajaro : lstaves) {
pajaro.vuela();
}
}
} // Fin de AveTest

Por qu no jala

Guajolote no vuela. Prohibe hacer algo que se


poda en la superclase.

Cmo se resuelve?
Factorizando:
Lo comn a todas las instancias de Ave es que
comen. As que Ave slo come.
De ella derivan dos subclases: las que vuelan y
las que no.
Cuervo es subclase de la las que vuelan.
Guajolote es subclase de las que no vuelan.

Es decir...
class Ave{
public void comer(){}
}
class AveVoladora extends Ave {
public void vuela()()
}
class AveNoVoladora extends Ave{}

Otro
class
protected
protected
public
void
m_width
}
public
void
m_height
}
public
int
return
}

Rectangle
int
int
setWidth(int
=

{
m_width;
m_height;
width)
{
width;

setHeight(int
=

height)

getWidth()

{
height;

{
m_width;

Otro
class

public
return
}
public
return
}
}

//
int

Rectangle
lo
getHeight()

int
m_width

getArea()
*

{
anterior
{
m_height;
{
m_height;

Cuadrado
class
Square
public
void
m_width
m_height
}
public
void
m_width
m_height
}
}

extends
setWidth(int
=
=

Rectangle
width)

{
{
width;
width;

setHeight(int
=
=

height)

{
height;
height;

Prueba
class
LspTest
{
private static Rectangle getNewRectangle()
{
// it can be an object returned by some factory ...
return
new
Square();
}

Prueba
public
static
void
main
(String
args[])
{
Rectangle
r
=
LspTest.getNewRectangle();
r.setWidth(5);
r.setHeight(10);
// user knows that r it's a rectangle.
// It assumes that he's able to set
// the width and height as for the base class
System.out.println(r.getArea());
// now he's surprised to see that the
// area is 100 instead of 50.
}
} // Fin de Prueba

Qu sali mal?
Todo cuadrado ES UN rectngulo, qu no?
Es que la relacin ES UN es un poco menos
superficial.
Lo de ES UN debe estar referido al
COMPORTAMIENTO, no slo a los atributos.
Un cuadrado es un caso particular de rectngulo, pero
NO puedo usarlo siempre que usaba un rectngulo.
Si tengo que modificar el programa para adecuarlo
cuando uso una subclase particular, estoy violando el
principio Open/Close, que generaliza el LSP.

You might also like