Вы находитесь на странице: 1из 0

LIDIA

Laboratorio de Investigacin y
desarrollo en Inteligencia Artificial
Departamento de Computacin
Universidade da Corua, Espaa
Programacin Orientada a Objetos
Tema 5: Principios de Diseo
Eduardo Mosqueira Rey
2
Objetivos
Introducir a los alumnos en el concepto de principios de
diseo.
Conocer los principales principios de diseo y
comprobar cmo las propiedades bsicas pueden
utilizarse para desarrollar modelos orientados a objetos
que cumplan los requisitos de simplicidad,
comprensibilidad, reutilizacin, etc.
Ver el impacto que los principios de diseo tienen en la
utilizacin de la herencia, distinguiendo los distintos
tipos de herencia que pueden aparecer.
Comparar los desarrollos realizados mediante herencia
con los desarrollos realizados mediante composicin y
discutir sus ventajas e inconvenientes.
3
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
ndice
1. Introduccin
2. Principio abierto-cerrado
3. Principio de sustitucin de Liskov
4. Diseo por contrato y subcontratacin
5. Principio de inversin de la dependencia
6. Principios de diseo y herencia
Tipos de herencia
Herencia vs. composicin
4
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
ndice
1. Introduccin
Reutilizacin
Patrones de diseo
Principios de diseo
5
Principios de Diseo
Introduccin
Reutilizacin
Principal objetivo de la orientacin a objetos:
Reutilizacin
Un desarrollo orientado a objetos no asegura de por
si que el cdigo sea reusable:
Es necesario que se codifique pensando en la reusabilidad.
No siempre se tiene tiempo para desarrollar el cdigo y,
adems, pensar en su futura reutilizacin.
Cmo conseguir diseos reusables
Entender en profundidad las implicaciones del uso de las
propiedades tpicas de la orientacin a objetos, como la
herencia, el polimorfismo, la ligadura dinmica, etc.
Seguir guas que nos indique cmo utilizar las propiedades
anteriores para conseguir diseos reusables.
6
Principios de Diseo
Introduccin
Patrones de diseo
Son soluciones reusables a problemas tpicos de diseo.
Inconveniente:
No son universalmente aplicables y suelen ser muy especficos del
tipo de problema que pretenden resolver.
Con la proliferacin de patrones en los ltimos aos, encontrar
el patrn ms apropiado para resolver nuestro problema de
diseo puede llegar ser una tarea complicada.
Principios de diseo
Son los principios bsicos que subyacen en los patrones.
Son un conjunto de recomendaciones que nos permitirn
desarrollar cdigo ms robusto y reusable.
Estas recomendaciones tienen un carcter ms bsico y
genrico que los patrones de diseo, por lo que pueden
aplicarse en dominios para los cuales no existe (o no hemos
encontrado) un patrn que nos satisfaga.
7
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
ndice
2. Principio abierto-cerrado
Mdulos abiertos vs. cerrados y herencia
Cdigos de ejemplo
8
Principios de Diseo
Principio abierto-cerrado
Tensin entre encapsulamiento y jerarqua
El encapsulamiento intenta proporcionar una barrera opaca tras
la que ocultar los mtodos y el estado
La herencia requiere abrir esta interfaz en cierto grado y puede
permitir el acceso a los mtodos y al estado a sus subclases
pero no a otro tipo de clases
Problema
Como conjugar estabilidad y proteccin de la informacin con
facilidad para extender un diseo
Solucin
Principio abierto-cerrado
Los mdulos (clases) deben ser a la vez abiertos (a su
extensin ) y cerrados (a su modificacin)
9
Principios de Diseo
Principio abierto-cerrado
Modulo abierto
Est disponible para ser extendido
Por ejemplo, debera ser posible expandir su conjunto de operaciones
o aadir campos a sus estructuras de datos
Mdulo cerrado
Su interfaz es estable y est bien definido
Su implementacin puede ser compilada y, tal vez, almacenada en una
biblioteca para ponerla a disposicin de otros clientes.
Herencia
La herencia permite abrir un mdulo a su extensin a travs de
subclases, mientras que la clase se mantiene cerrada.
Los elementos protegidos , invisibles para las clases externas pero
visibles para las subclases, facilitan dicha extensin
Problema: no todos los usos de la herencia garantizan que se cumpla
el p. abierto-cerrado ya que existen diseos que obligan a modificar la
clase padre cuando se produce un extensin por herencia de la misma
10
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Principio abierto-cerrado
Cdigo que NO cumple el principio abierto-cerrado
class Cl i ent e
{
// Atributos
private St r i ng nombr e;
private Cuent a cuent a;

// Mtodos constructores
public Cl i ent e
( St r i ng nombr e, int cant i dad)
{
this. nombr e = nombr e;
cuent a = new Cuent aCor r i ent e( cant i dad) ;
}

// Mtodos de acceso
public St r i ng get Nombr e( )
{ return nombr e;
}

public Cuent a get Cuent a( )
{ return cuent a;
}
}

class Pr uebaCl i ent e
{
public static void
mai n ( St r i ng [ ] ar gs)
{
Cl i ent e cJ uan =
new Cl i ent e ( "J uan" , 1000) ;
Cuent a c = cJ uan. get Cuent a( ) ;
c. r et i r ada ( 1000) ;
Syst em. out . pr i nt l n( " El sal do es " +
cJ uan. get Cuent a( ) . get Bal ance( ) ) ;
}
}
abstract class Cuent a
{ // Atributos
protected int bal ance;

// Mtodos constructores
public Cuent a ( int cant i dad)
{ bal ance = cant i dad; }

// Mtodos de acceso
public int get Bal ance( )
{ return bal ance; }

// Otros mtodos
public void r et i r ada( int cant i dad)
{
if ( this instanceof Cuent aCor r i ent e)
bal ance = bal ance - cant i dad;
else if ( this i nst anceof Cuent aPl azo)
bal ance = ( bal ance - cant i dad)
( ( cant i dad * 4) / 100) ;
}

public void i ngr eso ( int cant i dad)
{ if ( this i nst anceof Cuent aCor r i ent e)
bal ance = bal ance + cant i dad;
else if ( t hi s i nst anceof Cuent aPl azo)
if ( cant i dad > 600)
bal ance = bal ance + cant i dad;
}
}

class Cuent aCor r i ent e extends Cuent a
{ public Cuent aCor r i ent e ( int cant i dad)
{ super( cant i dad) ; }
}

class Cuent aPl azo extends Cuent a
{ public Cuent aPl azo ( int cant i dad)
{ super( cant i dad) ; }
}
El cdigo de las
superclase hace
referencia a las
subclases
Este cdigo debera
residir en la
subclase
11
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua

abstract class Cuent a
{
// Atributos
protected int bal ance;

// Mtodos constructores
public Cuent a ( int cant i dad)
{ bal ance = cant i dad; }

// Mtodos de acceso
public int get Bal ance( )
{ return bal ance; }

// Otros mtodos
public abstract void r et i r ada( int cant i dad) ;
public abstract void i ngr eso ( int cant i dad) ;
}

class Cuent aCor r i ent e extends Cuent a
{
public Cuent aCor r i ent e ( int cant i dad)
{ super( cant i dad) ; }

public void r et i r ada( int cant i dad)
{ bal ance = bal ance - cant i dad; }

public void i ngr eso ( int cant i dad)
{ bal ance = bal ance + cant i dad; }
}

class Cuent aPl azo extends Cuent a
{
public Cuent aPl azo ( int cant i dad)
{ super( cant i dad) ; }

publi c void r et i r ada( int cant i dad)
{ bal ance = ( bal ance - cant i dad) - ( ( cant i dad * 4) / 100) ; }

public void i ngr eso ( int cant i dad)
{ if ( cant i dad > 600) bal ance = bal ance + cant i dad; }
}
Principios de Diseo
Principio abierto-cerrado
Cdigo que SI cumple el principio abierto-cerrado
La superclase no
hace referencia a las
subclases
El cdigo de las
subclases est en
las subclases
12
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
ndice
3. Principio de sustitucin de Liskov
Tipos y subtipos
Principio de sustitucin de Liskov
Cdigos de ejemplo
13
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ppio. de sustitucin de Liskov
Tipos y subtipos
Los lenguajes de programacin, adems de la definicin de
tipos, suelen permitir la definicin de subtipos.
Definicin de subtipo
Un tipo B es subtipo de otro A si siempre que se requiera un
elemento de tipo A puede pasarse un elemento de tipo B sin
observar ningn cambio en la conducta del programa.
Ejemplo
Pascal permite que a una variable declarada como integer se le
asigne el valor de una variable cuyo tipo es un subrango de
integer (como puede ser 1..10)
El hecho de que se le pase a una funcin una variable de tipo
integer con el valor 5 o un subrango de 1 a 10 con el valor 5 no
afecta al resultado de dicha funcin.
14
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ppio. de sustitucin de Liskov
Tipos y subtipos en los lenguajes OO
Caractersticas
Los lenguajes OO unifican el concepto de clase con el
concepto de tipo.
Igualmente unifican los trminos de subclase y subtipo
Problema
El trmino subclase se refiere exclusivamente al mecanismo
de construir una nueva clase utilizando herencia.
No todas las subclases creadas son subtipos
El hecho de pasar una subclase a un mtodo que pide un
objeto de la superclase puede conllevar profundos cambios
el funcionamiento de dicho mtodo
15
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ppio. de sustitucin de Liskov
Principio de sustitucin de Liskov
Una subclase es un subtipo si cumple con el principio de sustitucin
de Liskov.
Citado por primera vez por Barbara Liskov (primera mujer en recibir un
doctorado en Computacin en EEUU en 1968) y su versin es:
Si para cada objeto o1 de tipo S existe un objeto o2 de tipo T de tal forma
que para todos los programas P definidos en trminos de T, la conducta de
P no cambia cuando o1 es sustituido por o2, entonces S es un subtipo de
T.
Una versin ms simple y orientada a objetos podra ser:
Aquellos mtodos que utilicen referencias a clases base (superclases)
deben ser capaces de usar objetos de clases derivadas (subclases) sin
notar la diferencia .
Resumiendo, para que un tipo B pueda ser considerado subtipo de A
tienen que cumplirse dos condiciones:
Una instancia de B puede legalmente ser asignada a una variable declarada
como de tipo A
Esta instancia de B puede ser utilizada por la variable declarada como A sin
un cambio observable en la conducta.
16
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ppio. de sustitucin de Liskov
Principio de sustitucin de Liskov
Una subclase B de una superclase A
Puede legalmente ser asignada a una variable declarada como de tipo A
(debido al polimorfismo)
Asignar subclases a variables definidas como superclases produce
cambios en la conducta de estas variables? DEPENDE
De que depende
Si la subclase no altera el comportamiento de la superclase no hay
problema
Si la subclase altera el comportamiento de la superclase
(sobreescritura) DEPENDE
De que depende
De cmo se haga la sobreescritura
Prohibir la sobreescritura es demasiado restrictivo, lo que hay que
hacer es identificar las sobreescrituras problemticas y evitarlas
17
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ppio. de substitucin de Liskov
Clase Rectngulo
Qu problema tiene el cdigo anterior?

.

class Rect angul o
{
private int al t o;
private int ancho;

public int get Al t o( )
{ return al t o; }

public void set Al t o( int val or )
{ al t o = val or ; }

public int get Ancho( )
{ return ancho; }

public void set Ancho( int val or )
{ ancho = val or ; }
}

class Cuadr ado extends Rect angul o
{
private void set Di mensi ones ( int val or )
{ super . set Al t o( val or ) ;
super . set Ancho( val or ) ;
}

public void set Al t o( int val or )
{ set Di mensi ones( val or ) ; }

public void set Ancho( int val or )
{ set Di mensi ones( val or ) ; }
}
Redefinimos setAlto y
setAncho de forma que
cambien las dos dimensiones
del Rectngulo
Clase Cuadrado
18
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ppio. de substitucin de Liskov
Clase ClienteRectangulo
Prueba de utilizacin de ClienteRectangulo

class Cl i ent eRect angul o
{
public static void met odoCl i ent e ( Rect angul o r )
{
r . set Ancho( 5) ;
r . set Al t o( 6) ;
if ( ( r . get Ancho( ) * r . get Al t o( ) ) ==30)
Syst em. out . pr i nt l n( "Mul t i pl i caci n cor r ect a. . . ") ;
else
Syst em. out . pr i nt l n( "Est o es i mposi bl e. . . ") ;
}
}

class Pr ueba
{
public static void mai n ( St r i ng [ ] ar gs)
{
Rect angul o r = new Rect angul o( ) ;
Cuadr ado c = new Cuadr ado( ) ;
Cl i ent eRect angul o. met odoCl i ent e( r ) ; // Multiplicacin correcta...
Cl i ent eRect angul o. met odoCl i ent e( c) ; // Esto es imposible...
}
}
Este mtodo espera
un rectngulo
El rea de un
rectngulo de ancho
5 y alto 6 TIENE que
ser 30
Si pasamos un cuadrado (posible por
el polimorfismo de inclusin) el rea
no es 30
19
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ppio. de substitucin de Liskov
P. de substitucin y sobreescritura
La clase Cuadrado no cumple el principio de
sustitucin de Liskov ya que puede legalmente
sustituir a un Rectangulo pero la sobreescritura que
realiza provoca un cambio observable en su
conducta.
Muchas veces las subclases modifican el
comportamiento de la superclase de la cual heredan
sin necesidad de contradecir el principio de
sustitucin
cmo saber si una modificacin cumple o incumple
el principio de sustitucin?, la solucin puede estar
en el diseo por contrato.
20
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
ndice
4. Diseo por contrato y subcontratacin
Diseo por contrato
Subcontratacin
Principio de subcontratacin
Cdigos de ejemplo
21
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ds. por contrato y subcontratacin
Diseo por contrato
Consiste en que los mtodos de las clases declaren
cules son sus precondiciones y postcondiciones.
Precondicin
Una condicin que debe ser cierta para que el mtodo se
ejecute correctamente.
Postcondicin
Una condicin que es cierta despus de la ejecucin del
mtodo.
Contrato entre un mtodo y el cdigo que lo utiliza
Si me pasas los parmetros tal y como indica la
precondicin entonces me comprometo a devolverte el
resultado del mtodo conforme a las condiciones impuestas
en la postcondicin .
22
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ds. por contrato y subcontratacin
Subcontratacin
Cuando una subclase redefine un mtodo de la
superclase podemos decir que est subcontratando
dicho mtodo
Como todo subcontrato, la subclase debe garantizar
que el contrato establecido en la clase padre se
cumple
Sin embargo, esto no quiere decir que el contrato sea
el mismo sino que debe cumplirse el principio de
subcontratacin
Principio de subcontratacin
Una precondicin slo puede substituirse por otra
precondicin ms dbil (o igual) y una postcondicin
por otra postcondicin ms severa (o igual).
23
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ds. por contrato y subcontratacin
Ejemplo de condiciones

A: (P 0) and (P 100)
B es ms dbil que A porque incluye
a todos los casos de A adems de
nuevos casos.

A es ms estricta que B porque
incluye solo un subconjunto de los
casos que contempla B
B: (P 0)
Conjunto de los posibles valores de P
24
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ds. por contrato y subcontratacin
Cumple este cdigo el principio de subcontratacin?

ClaseBase
+Calcula(P: int): int
ClienteClaseBase
+metodoCliente(CB:ClaseBase:void)

PreCD: (P0) and (P100)
PostCD: (metodoX 0)
ClaseDerivada
+Calcula(P: int): int

PreCD: (P0)
PostCD: (metodoX 0)
and (metodoX 10)
25
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ds. por contrato y subcontratacin
Cumple este cdigo el principio de subcontratacin?


ClaseBase
+Calcula(P: int): int
ClienteClaseBase
+metodoCliente(CB:ClaseBase:void)

PreCD: (P0) and (P100)
PostCD: (metodoX 0)
ClaseDerivada
+Calcula(P: int): int

PreCD: (P0) and (P50)
PostCD: (metodoX -100)
26
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ds. por contrato y subcontratacin
Cumple este cdigo el principio de subcontratacin?

Rectangulo
+getAlto(): int
+setAlto(valor:int):void
+getAncho(): int
+setAncho(valor:int):void
- alto: int
- ancho: int
Cuadrado
- setDimensiones(valor:int): void
+setAlto(valor:int):void
+setAncho(valor:int):void
ClienteRectangulo
+metodoCliente(r:Rectngulo):void
PreCD: valor 0
PostCD: (alto = valor) and
(no hay efectos
laterales)
PreCD: valor 0
PostCD: (ancho=valor)
(no hay efectos
laterales)

PreCD: valor 0
PostCD: (alto = valor) and
(ancho = valor)

PreCD: valor 0
PostCD: (alto = valor) and
(ancho=valor)
27
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
ndice
5. Principio de inversin de la dependencia
Introduccin
Principio de inversin de la dependencia
28
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ppio. de inversin de la dependencia
Qu problema existe en el siguiente cdigo?
Ar r ayLi st l i st a = new ArrayList( ) ;
29
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ppio. de inversin de la dependencia
El principio de inversin de la dependencia podra resumirse como:
Depende de abstracciones no de concreciones
Explicacin
Es decir los mdulos de alto nivel no deberan depender de los
mdulos de bajo nivel (como ocurre en el diseo top-down) ya que un
cambio en los detalles afectara a los mdulos ms generales (de ah el
termino inversin de la dependencia).
Bsicamente quiere decir que las clases deberan acoplarse a travs
de clases abstractas o interfaces y nunca directamente
El motivo es claro, intercalar un interfaz entre dos clases concretas
hace que estas sean menos dependientes entre si, la clase que
implementa el interfaz puede cambiar sin que afecte a la clase que usa
el interfaz
Siendo prcticos este principio no debe aplicarse siempre, sino sobre
aquellas clases cuya implementacin pueda cambiar en un futuro. Si
una clase concreta es estable y bien definida no tendra que haber
ningn problema en usarla directamente
30
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Ppio. de inversin de la dependencia
Problema
La solucin que proponemos sigue referenciando a ArrayList, aunque
sea nicamente en el proceso de creacin
Solucin
Se pueden utilizar clases con mtodos que se dedican a construir
instancias de objetos (patrn factoria)
Pero ahora en vez de depender de ArrayList dependemos de
ListaFactoria. Es cierto, pero ListaFactoria puede implementarse como
una clase abstracta o un interfaz
Lema y contralema
La mayora de los problemas en computacin pueden ser resueltos
aadiendo un nivel de indireccin
La mayora de los problemas en rendimiento pueden ser resueltos
eliminando un nivel de indireccin
Li st l i st a = new ArrayList( ) ;
Li st l i st a = Li st aFact or i a. cr eaLi st a( ) ;
31
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
ndice
6. Principios de diseo y herencia
Tipos de herencia
Herencia vs. composicin
32
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Principios de Diseo
Principios de diseo y herencia
Principios de diseo y herencia
La herencia es quiz el mecanismo ms potente de reutilizacin
que poseen los LOO
Pero muchos de sus usos pueden llegar a ser ineficientes e
incluso algunos estn clasificados como antipatrones
Los principios de diseo nos indican cmo utilizar
correctamente el mecanismo de herencia
Tipos de herencia
Caracterizacin de los usos ms habituales de la herencia
No pretende ser una clasificacin exhaustiva ni mutuamente
excluyente (un cdigo puede pertenecer a varios tipos)
33
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Tipos de herencia
Herencia de especializacin
Es una de las formas ms comunes de uso de la
herencia.
Consiste en crear subclases especializadas, a partir
de una clase padre, que satisfagan las
especificaciones de dicha clase padre en todos los
aspectos relevantes (lo que puede interpretarse
como que cumplen el principio de subcontratacin).
En este tipo de herencia las subclases son subtipos
y el principio de sustitucin puede aplicarse sin
problemas.
34
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Tipos de herencia
Herencia de especializacin (ejemplo)
A la hora de definir el applet hacemos que herede las
caractersticas principales de funcionamiento de la
clase Applet (o JApplet) como setSize o setName.
Nuestro applet necesitar mtodos especializados en
algunos casos, como por ejemplo cuando se invoca
el mtodo paint. En este caso nuestra clase
redefinir el mtodo de la subclase y lo cambiar por
uno ms adecuado.
import j ava. awt . Gr aphi cs;
import j ava. appl et . Appl et ;
public class Hol aMundoAppl et extends Appl et
{ public void pai nt ( Gr aphi cs g)
{ g. dr awSt r i ng ( " Hol a Mundo! " , 25, 25) ; }
}
35
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Tipos de herencia
Herencia de especificacin
Junto con el anterior forma la utilizacin ms comn e ideal de la
herencia
La herencia de especificacin consiste en una clase padre que indica
la firma de unos mtodos pero no su implementacin, la
implementacin es incluida en las subclases.
En Java podemos implementar este tipo de herencia a travs de las
clases abstractas y los interfaces. La herencia de especificacin
tambin cumple el principio de sustitucin.
Herencia de extensin
La herencia de extensin ocurre cuando la subclase aade nuevo
comportamiento a la clase padre pero no modifica ni altera los
elementos heredados como ocurra en la herencia de especializacin.
En este caso como la funcionalidad de la clase padre permanece
intacta, la subclasificacin de extensin no contraviene el principio de
sustitucin, por lo que las subclases son siempre subtipos.
36
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Tipos de herencia
Herencia de construccin
Se denomina herencia de construccin cuando no existe relacin
lgica entre la superclase y la subclase pero esta ltima puede
aprovecharse de las funcionalidades de la superclase.
Problema:
Puede romper directamente el principio de sustitucin, formando clases
que no son subtipos
Ventaja:
Es una manera sencilla de desarrollar nuevas abstracciones
Ejemplo:
En el API de Java tenemos una clase Stack que hereda de la clase Vector.
Como abstracciones, los conceptos de pila y vector tienen poco en comn,
sin embargo, desde un punto de vista pragmtico la utilizacin de la clase
Vector simplifica en gran manera la implementacin de la pila.
En el caso de la clase Stack el principio de sustitucin se cumple ya que
adems de una herencia de construccin se lleva a cabo una herencia de
extensin
Sin embargo, lo que no se est cumpliendo es el interfaz propio de una pila,
ya que la herencia permite el acceso a elementos de la pila que no son su
cabecera a travs de los mtodos heredados de Vector.
37
Pp. de Diseo y Herencia
Tipos de herencia
Herencia de construccin
public class Vect or extends Abst r act Li st i mpl ement s Li st ,
Cl oneabl e, j ava. i o. Ser i al i zabl e
{
public boolean i sEmpt y ( ) {. . . }
public synchronized void set Si ze( i nt newSi ze) {. . . }
public int si ze( ) {. . . }
public synchronized void addEl ement ( Obj ect obj ) {. . . }
public synchronized void r emoveEl ement At ( int i ndex) {. . . }
public synchronized Obj ect el ement At ( int i ndex) {. . . }
public synchronized Obj ect f i r st El ement ( ) {. . . }
public synchronized Obj ect l ast El ement ( ) {. . . }
public int i ndexOf ( Obj ect el em) {. . . }
public int l ast I ndexOf ( Obj ect el em) {. . . }
. . .
}
38
Pp. de Diseo y Herencia
Tipos de herencia
Herencia de
construccin (cont.)
public class St ack extends Vect or
{
public St ack( ) {}
public Obj ect push ( Obj ect i t em)
{ addEl ement ( i t em) ;
return i t em;
}
public synchronized Obj ect pop( )
{ Obj ect obj ;
int l en = si ze( ) ;
obj = peek( ) ;
r emoveEl ement At ( l en - 1) ;
return obj ;
}
public synchronized Obj ect peek( )
{ int l en = si ze( ) ;
if ( l en == 0)
throw new Empt ySt ackExcept i on( ) ;
return el ement At ( l en - 1) ;
}
public boolean empt y( )
{ return si ze( ) == 0; }
public synchronized int sear ch( Obj ect o)
{ int i = l ast I ndexOf ( o) ;
if ( i >= 0)
{ return si ze( ) - i ; }
return - 1;
}
}
Si heredamos de
Vector podemos
aplicar los mtodos
de Vector sobre la
pila es deseable?
39
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Tipos de herencia
Herencia de limitacin
La herencia de limitacin ocurre cuando la conducta de la
subclase es ms restrictiva que la conducta de la clase padre.
Esto se consigue porque mtodos de la subclase redefinen el
comportamiento de mtodos de la superclase y hacen que su
ejecucin sea considerada ilegal.
La herencia de limitacin no cumple por tanto el principio de
sustitucin.
Por ejemplo la clase Stack podra limitar la utilizacin de alguno
de los mtodos heredados de Vector.
Herencia de combinacin
Ocurre cuando se da la herencia mltiple.
En Java no existe este tipo de herencia pero como ya hemos
visto puede simularse un comportamiento similar a travs de
los intefaces.
40
Pp. de Diseo y Herencia
Tipos de herencia
Herencia de limitacin
class St ack extends Vect or
{
. . .
public int i ndexOf ( Obj ect obj )
{ throw new j ava. l ang. Unsuppor t edOper at i onExcept i on( "i ndexOf ") ; }
public Obj ect el ement At ( int i ndex)
{ throw new j ava. l ang. Unsuppor t edOper at i onExcept i on( "el ement At ") ; }
}
Evitamos que se llamen a los mtodos de Vector
sobre la pila pero con el coste de obtener
excepciones en tiempo de ejecucin
41
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Tipos de herencia
Resumiendo
Herencia de especializacin
Las subclases sobreescriben a la superclase manteniendo el
principio de sustitucin
Herencia de especificacin
La superclase no tiene cdigo (es abstracta o un interfaz)
Herencia de extensin
La subclase no sobreescribe el cdigo de la superclase sino que
aade cdigo nuevo
Herencia de construccin
Establece una relacin de herencia entre dos clases aunque no
estn lgicamente relacionadas. Puede incumplir el principio de
sustitucin
Herencia de limitacin
La superclase sobreescribe y limita el comportamiento de la
superclase. Incumple el principio de sustitucin
42
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Herencia vs. composicin
Posibilidades de desarrollo de una nueva clase
Codificar una clase empezando desde cero:
Suele ser lo habitual y tiene la ventaja de que nos da libertad para
disear la clase como nosotros queramos
Tiene el inconveniente de exigir mucho trabajo que puede ser
evitado reutilizando clases.
Utilizar y modificar una clase ya existente:
Podemos utilizar una clase ya existente y modificarla para que
cumpla nuestras especificaciones
El esfuerzo de codificacin es menor que empezando desde cero
No es posible de utilizar si no disponemos del cdigo fuente de la
clase a modificar
Si ambas clases conviven en el mismo programa estaremos
repitiendo cdigo
43
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Herencia vs. composicin
Posibilidades de desarrollo de una nueva clase (cont.)
Reutilizar a travs de los mecanismos de herencia:
Es el mecanismo ms popular de reutilizacin en los lenguajes
orientados a objetos
Es muy potente pero su uso debe ser realizado con precaucin ya
que puede dar lugar a construcciones incorrectas o poco eficaces.
Reutilizar a travs de los mecanismos de composicin:
Una alternativa a la reutilizacin a travs de la herencia es la
reutilizacin a travs de la composicin.
Tanto la composicin como la herencia permiten reutilizar clases
sin disponer del cdigo fuente y sin repetir cdigo dentro del
programa
44
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Herencia vs. composicin
Caractersticas de la composicin
En muchas situaciones es fcil distinguir el tipo de jerarqua a
utilizar:
Un hocico ES_PARTE_DE un perro
Un perro ES_UN tipo de animal
hocico ES_UN perro o perro ES_PARTE_DE animal son
claramente incorrectas
No siempre es fcil distinguir el tipo de jerarqua a utilizar para
resolver un problema.
Por ejemplo cmo utilizar un vector para crear una pila.
Java se ha decantado por la herencia (de construccin) pero podra
haberse utilizado la composicin
Stack definido a travs de composicin
Se utiliza el vector como mecanismo interno (y privado) de
almacenamiento de los datos de la pila
La clase Stack va a delegar su funcionamiento en mtodos de la clase
Vector (concepto de Delegacin)
45
Pp. de Diseo y Herencia
Herencia vs. composicin
Clase Stack definida mediante composicin
class St ack
{
private Vector dat os;
public St ack ( )
{ dat os = new Vect or ( ) ; }
public boolean i sEmpt y ( )
{ return dat os. i sEmpt y( ) ; }
public Obj ect push ( Obj ect i t em)
{ dat os. addEl ement ( i t em) ;
return i t em;
}
public Obj ect peek ( )
{ return dat os. l ast El ement ( ) ; }
public Obj ect pop ( )
{ Obj ect obj = dat os. l ast El ement ( ) ;
dat os. r emoveEl ement At ( dat os. si ze( ) - 1) ;
return obj ;
}
}
46
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Herencia vs. composicin
Ventajas de la herencia:
Lleva implcito el principio de sustitucin.
Esto quiere decir que podemos pasar una pila en aquellos lugares en los
que se espere un vector. Lo cual no es posible en la composicin.
El cdigo a escribir es menor.
No es necesario escribir ningn cdigo para acceder a los elementos de la
superclase.
En la composicin necesitamos definir mtodos de enlace para acceder a la
funcionalidad de la clase utilizada como base.
Evita el tener que llamar a dos funciones para acceder a las
funcionalidades de la clase base
Como ocurre en los mtodos de enlace de la composicin.
Permite el acceso acceso a los elementos protegidos
En la composicin slo tenemos acceso a aquellos mtodos declarados
como public (o protected si estuviramos en el mismo paquete Java).
Solucin ms estructurada
Porque las relaciones entre clases son ms obvias
47
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Herencia vs. composicin
Ventajas de la composicin:
La composicin indica con claridad cuales son las operaciones
que podemos utilizar en la nueva estructura de datos definida.
En la clase Stack definida por composicin solo hay disponibles
cuatro mtodos aparte del constructor: isEmpty, push peek y pop.
La clase Stack definida por herencia no slo tiene los mtodos
declarados en su clase sino todos aquellos heredados deVector.
La herencia es menos clara de comprender porque obliga a analizar
la estructura de herencia para comprender mejor el funcionamiento
de la clase creada ( yo-yo )
La herencia presupone implcitamente que las subclases son
subtipos, por lo que todos los mtodos definidos para los
vectores pueden utilizarse con las pilas.
Esto puede dar lugar a comportamientos indeseados, por ejemplo,
podramos eliminar elementos en la pila sin ser a travs de su cima.
Para evitar esto la nica solucin es utilizar la herencia de
limitacin, lo que obliga a redefinir aquellos elementos que no
deseamos heredar.
48
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Herencia vs. composicin
Ventajas de la composicin (cont.):
En composicin el hecho de que la clase Vector se utilice como
mecanismo de almacenamiento para las pilas es slo un detalle de
implementacin.
Con esta tcnica sera sencillo reimplementar la clase para hacer que
utilice otro mecanismo de almacenamiento (como una lista enlazada), con
un impacto mnimo para los usuarios de la clase Stack.
Sin embargo cambiar el hecho de que la clase Stack herede de la clase pila
tiene unos efectos ms complicados de sobrellevar
La composicin permite simular herencia mltiple
En Java y en otros lenguajes slo se permite una herencia mltiple limitada
a travs de interfaces.
Con la composicin podemos simular un tipo de herencia mltiple creando
un nuevo objeto que contenga objetos de distintas clases y utilizando sus
funcionalidades.
La composicin es una solucin ms general
Toda extensin de una clase que puede realizarse por herencia tambin
puede realizarse por composicin (excepto quiz en lo que concierne a los
protected)
49
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Pp. de Diseo y Herencia
Herencia vs. composicin
Herencia o composicin?
Las dos tcnicas son tiles y usadas frecuentemente en la
programacin orientada a objetos.
La respuesta depende de cada caso en particular y puede
depender del principio de sustitucin.
Si se espera utilizar la clase Stack en lugares destinados a incluir
un vector entonces lo ms adecuado sera la herencia, en caso
contraro habra que analizar la posibilidad de utilizar la
composicin.
Consejo
Que se utilice la herencia exclusivamente en aquellas relaciones
que claramente corresponden a un tipo ES_UN.
En caso de duda lo ms corriente es que la relacin ms adecuada
sea la de composicin.
50
Eduardo Mosqueira Rey Departamento de Computacin Universidade da Corua
Bibliografa
Bibliografa fundamental
Budd, T. Understanding object-oriented programming with Java , Addison-
Wesley, Reading, MA, 1998.
Knoernschild, K. Java design: objects, UML and process , Addison-Wesley,
Boston, MA, 2002.
Bibliografa complementaria
Liskov, B. Data Abstraction and Hierarchy, SIGPLAN Notices, 23,5 (May,
1988).
Meyer, B. Appliyng Design by Contract, IEEE Computer, vol. 25, no. 10, pp. 40-
51 (October, 1992).
Bibliografa en Internet
Martin, R.C. The open-closed principle, C++ Report, 8(1), pp. 37-43, January
1996. URL: http://www.objectmentor.com/resources/articles/ocp.pdf
Martin, R.C. The Liskov substitution principle, C++ Report, 8(3), p. 14, 16-17,
20--23, March 1996. URL:
http://www.objectmentor.com/resources/articles/lsp.pdf
Martin, R.C. The Dependency Inversion Principle, C++ Report, 8(6), pp. 61-66,
June 1996. URL: http://www.objectmentor.com/resources/articles/dip.pdf
Eiffel Software Inc. Design by contract: building bug-free object-oriented
software . URL:
http://www.eiffel.com/doc/manuals/technology/contract/page.html

Вам также может понравиться