Professional Documents
Culture Documents
TEMA 3 HERENCIA
Cristina Cachero, Pedro J. Ponce de Len
versin 3 (Curso 10/11) (3 sesiones)
POO
Entender el mecanismo de abstraccin de la herencia. Distinguir entre los diferentes tipos de herencia Saber implementar jerarquas de herencia en C++ Saber discernir entre jerarquas de herencia seguras (bien definidas) e inseguras. Reutilizacin de cdigo: Ser capaz de decidir cundo usar herencia y cundo optar por composicin.
No persist.
Asociacin Todo-Parte
" "
C1
C2
Uso (depend) C1 C2
"
Agregacin Composicin
Entre clases
"
Generalizacin
vehiculo areo
avion
helicoptero
HERENCIA Motivacin
Florista cobrar() darRecibo() Panadero cobrar() darRecibo() Vendedor coches
....
cobrar() darRecibo()
Clasificacin y generalizacin
!
La herencia consigue clasificar los tipos de datos (abstracciones) por variedad, acercando un poco ms el mundo de la programacin al modo de razonar humano.
!
Este modo de razonar humano se denomina GENERALIZACIN, y da lugar a jerarquas de generalizacin/especializacin. La implementacin de estas jerarquas en un lenguaje de programacin da lugar a jerarquas de herencia.
La generalizacin es una relacin semntica entre clases, que determina que la interfaz de la subclase debe incluir todas las propiedades pblicas y privadas de la superclase. Disminuye el nmero de relaciones (asociaciones y agregaciones) del modelo Aumenta la comprensibilidad, expresividad y abstraccin de los sistemas modelados. Todo esto a costa de un mayor nmero de clases
7
HERENCIA Definicin
!
La herencia es el mecanismo de implementacin mediante el cual elementos ms especficos incorporan la estructura y comportamiento de elementos ms generales (Rumbaugh 99)
Gracias a la herencia es posible especializar o extender la funcionalidad de una clase, derivando de ella nuevas clases. La herencia es siempre transitiva: una clase puede heredar caractersticas de superclases que se encuentran muchos niveles ms arriba en la jerarqua de herencia.
!
Ejemplo: si la clase Perro es una subclase de la clase Mamfero, y la clase Mamfero es una subclase de la clase Animal, entonces el Perro heredar atributos tanto de Mamfero como de Animal.
La clase A se debe relacionar mediante herencia con la clase B si A ES-UN B. Si la frase suena bien, entonces la situacin de herencia es la ms probable para ese caso
! ! ! ! !
Un pjaro es un animal Un gato es un mamfero Un pastel de manzana es un pastel Una matriz de enteros es un matriz Un coche es un vehculo
Sin embargo, si la frase suena rara por una razn u otra, es muy probable que la relacin de herencia no sea lo ms adecuado. Veamos unos ejemplos:
! ! ! !
Un pjaro es un mamfero Un pastel de manzana es una manzana Una matriz de enteros es un entero Un motor es un vehculo
10
La herencia como reutilizacin de cdigo: Una clase derivada puede heredar comportamiento de una clase base, por tanto, el cdigo no necesita volver a ser escrito para la derivada. ! Herencia de implementacin La herencia como reutilizacin de conceptos: Esto ocurre cuando una clase derivada sobrescribe el comportamiento definido por la clase base. Aunque no se comparte ese cdigo entre ambas clases, ambas comparten el prototipo del mtodo (comparten el concepto). ! Herencia de interfaz
11
Tipos de Herencia
!
12
Tipos de Herencia
!
Simple/Mltiple
!
13
Tipos de Herencia
!
De implementacin/de interfaz
!
De implementacin: La implementacin de los mtodos es heredada. Puede sobreescribirse en las clases derivadas. De interfaz: Slo se hereda la interfaz, no hay implementacin a nivel de clase base (interfaces en Java, clases abstractas en C++)
14
Herencia
!
Solapada/Disjunta
!
Determina si un objeto puede ser a la vez instancia de dos o ms subclases de ese nivel de herencia. C++ no soporta la herencia solapada (tipado fuerte) Determina si todas las instancias de la clase padre son a la vez instancias de alguna de las clases hijas (completa) o, por el contrario, hay objetos de la clase padre que no pertenecen a ninguna subcategora de las reflejadas por las clases hijas (incompleta). Determina si un determinado objeto puede pasar de ser instancia de una clase hija a otra dentro de un mismo nivel de la jerarqua de herencia. C++ no soporta la herencia dinmica (tipado fuerte)
Completa/Incompleta
!
Esttica/Dinmica
!
16
Herencia
Caracterizacin: ejemplos
17
HERENCIA DE IMPLEMENTACIN
Herencia Simple
19
La parte privada de una clase base no es directamente accesible desde la clase derivada.
Herencia en C++
!
!
class Circulo : Figura2D { public: void vaciarCirculo() { colorRelleno=NINGUNO; //OK, protected } ... };
21
Herencia Protegida
class Circulo : protected Figura2D { ... };
<<protected>>
Herencia Privada
class Circulo : private Figura2D { ... };
<<private>>
22
Padre
<<??>>
+inicializaTodoAUno()
<<public>>
Hija
Implementa el mtodo Hija::inicializaTodoAUno() suponiendo que la herencia entre Abuela y Padre es: Pblica Protegida Privada
+inicializaTodoAUno()
24
Herencia Simple
!
Aadir nuevos mtodos/atributos propios de la clase derivada Modificar los mtodos heredados de la clase base
!
REFINAMIENTO: se aade comportamiento nuevo antes y/o despus del comportamiento heredado. (Simula, Beta) (se puede simular en C++, Java) ! C++, Java: Constructores y destructores se refinan REEMPLAZO: el mtodo heredado se redefine completamente, de forma que sustituye al original de la clase base.
26
Siempre son definidos para las clases derivadas Creacin de un objeto de clase derivada: Se invoca a todos los constructores de la jerarqua Orden de ejecucin de constructores: Primero se ejecuta el constructor de la clase base y luego el de la derivada.
27
A B C
28
Esto implica que la clase derivada aplica una poltica de refinamiento: aadir comportamiento al constructor de la clase base. Ejecucin implcita del constructor por defecto de clase base al invocar a un constructor de clase derivada. Ejecucin explcita de cualquier otro tipo de constructor en la zona de inicializacin (refinamiento explcito). En particular, el constructor de copia.
(CONSEJO: Inicializacin de atributos de la clase base: en la clase base, no en la derivada)
29
Ejemplo
class Figura2D { Color colorRelleno; public: Figura2D() : colorRelleno(NINGUNO) {} Figura2D(Color c) : colorRelleno(c) {} Figura2D(const Figura2D& f) : colorRelleno(f.colorRelleno) {} ...}; class Circulo : Figura2D { double radio; public: Circulo() : radio(1.0) {} //llamada implcita a Figura2D() Circulo(Color col, double r) : Figura2D(col), radio(r) {} Circulo(const Circulo& cir) : Figura2D(cir), radio(cir.radio) {} ...};
30
El destructor no se hereda.
! !
Siempre es definido para la clase derivada Destruccin de un objeto de clase derivada: se invoca a todos los destructores de la jerarqua Primero se ejecuta destructor de la clase derivada y luego el de la clase base. Llamada implcita a los destructor de la clase base.
31
A B C
32
Construccion/destruccin en resumen
!
33
35
36
37
TCuentaJoven
- int edad + + + + + + + + TCuentaJoven() TCuentaJoven(const TCuentaJoven&) ~TCuentaJoven() operator=(const TCuentaJoven&) : TCuenta& abonarInteresMensual() : void getEdad() : int setEdad(int) : void mostrar() : void
38
40
43
tc
tc->getEdad(); // ERROR POR QU??
44
! ! !
El constructor de copia se refina explcitamente. El operador de asignacin se reemplaza. De ah que la forma cannica de la clase implique siempre definir estas cuatro funciones miembro. Las propiedades de clase definidas en la clase base tambin son compartidas (heredadas) por las clases derivadas.
47
HERENCIA DE IMPLEMENTACIN
Herencia Mltiple
51
TCuenta
TEmpresa
TCuentaEmpresarial
Clase Madre1
Clase Madre2
HERENCIA DE INTERFAZ
Herencia de interfaz
!
La herencia de interfaz NO hereda cdigo Slo se hereda la interfaz (a veces con una implementacin parcial o por defecto). Se utiliza exclusivamente con el propsito de garantizar la sustituibilidad.
57
Herencia de interfaz
A* obj =
new B();
58
El principio de sustitucin
Debe ser posible utilizar cualquier objeto instancia de una subclase en el lugar de cualquier objeto instancia de su superclase sin que la semntica del programa escrito en los trminos de la superclase se vea afectado. (Liskov !"#$%
Subtipo& Una clase B, subclase de A, es un subtipo de A si podemos sustituir instancias de A por instancias de B en cualquier situacin y sin ningn efecto observable.
El principio de sustitucin
$aracteri%an los ob etos por su clase $aracteri%an los ob etos por su comportamiento
Lengua e debilmente tipado& funcion medir(objeto) { si (objeto <= 5) sino si (objeto == 0) ...}
El principio de sustitucin
Java& directamente
class class Dependiente Dependiente {{ public: public: int int cobrar(); cobrar(); void void darRecibo(); darRecibo(); ...}; ...}; class class Panadero Panadero :: public public Dependiente Dependiente {...} {...} Panadero Panadero p; p; Dependiente& .. Dependiente& d1=p; d1=p; // // sustit sustit Dependiente* .. Dependiente* dd =&p; =&p; // // sustit sustit Dependiente Dependiente d!=p; d!=p; // NO sustit.: // NO sustit.: object object slicing slicing
class class Dependiente Dependiente {{ public public int int cobrar(); cobrar(); public void public void darRecibo(); darRecibo(); ...}; ...}; class class Panadero Panadero e"tends e"tends Dependiente Dependiente {...} {...} Panadero Panadero pp == ne# ne# Panadero(); Panadero(); Dependiente d1=p; Dependiente d1=p; // // sustit. sustit.
HERENCIA DE INTERFAZ
Ob etivos!
6omento en el que se identifica el fragmento de cdigo a e ecutar asociado a un mensa e !llamada a m(todo# o el ob eto concreto asociado a una variable.
'entaja& )L(.*/*L*D-D
Enlace est#tico! el tipo de ob eto que contiene una variable se determina en tiempo de compilacin.
$irculo c7
Enlace din#$ico! el tipo de ob eto al que 8ace referencia una variable no est" predefinido, por lo que el sistema gestionar" la variable en funcin de la naturale%a real del ob eto que referencie durante la e ecucin. Lengua es como 'malltal9 siempre utili%an enlace din"mico con variables.
$,, slo permite enlace din"mico con variables cuando (stos son punteros o referencias, y slo dentro de erarqu:as de 8erencia.
Enlace est#tico! la eleccin de qu( m(todo ser" el encargado de responder a un mensa e se reali%a en tiempo de compilacin, en funcin del tipo que ten:a el ob eto destino de la llamada en tiempo de compilacin.
TCuentaJoven tcj; TCuenta tc; tc=tcj; // object slicing tc.abonarInteresMensual(); // Enlace esttico: TCuenta::abonarInteresMensual()
Enlace din#$ico la eleccin de qu( m(todo ser" el encargado de responder a un mensa e se reali%a en tiempo de e ecucin, en funcin del tipo correspondiente al ob eto que referencia la variable mediante la que se invoca al m(todo en el instante de la e ecucin del mensa e.
'e pretende invocar a ciertos m(todos sobreescritos desde referencias a ob etos de la clase base !aprovec8ando el principio de sustitucin#.
1n muc8os lengua es OO este rasgo es soportado de forma natural& ?or e emplo, en -ava, los m(todos son virtuales por defecto. 1n $,, para que esto sea posible&
1l m(todo debe ser declarado en la clase base como $-todo virtual !mediante la palabra clave virtual#. 1sto indica que tiene enlace din"mico. La clase derivada debe proporcionar su propia implementacin del m(todo.
class class $%uenta $%uenta {{ ... ... virtual virtual ~T ~T uenta(); uenta(); }; }; delete tc; // '(u) destructor se invoca* +$%uenta&oven()
1n resumen, si una clase tiene m(todos virtuales 1s posible utili%ar el principio de sustitucin. 0eredar de ella y sobreescribir los m(todos virtuales ?ara destruir ob etos derivados desde punteros a clase base, el destructor de esta clase base debe declararse como m(todo virtual.
Alguno de sus m(todos no est" definido& son m(todos abstractos 2o se pueden crear ob etos de estas clases. ': se pueden crear referencias !o punteros# a ob eto de una clase abstracta !que apuntar"n a ob etos de clases derivadas#
?ropsito& *aranti%ar que las clases derivadas proporcionan una implementacin propia de ciertos m(todos. 'e garanti%a el principio de sustitucin.
01)12$+A 31 +2T1)4A5
Clases abstractas
Las clases que deriven de clases abstractas !o interfaces# deben implementar todos los m(todos abstractos !o ser"n a su ve% abstractas#. La clase derivada implementa el interfa% de la clase abstracta.
01)12$+A 31 +2T1)4A5
2otacin U6L para clases abstractas
Vehculo
CLASE ABSTRACTA
CLASE ABSTRACTA
Terrestre {abstract}
CLASE ABSTRACTA
Areo
Coche
Bicicleta
Avin
Helicptero
CLASES CONCRETAS
01)12$+A 31 +2T1)4A5
01)12$+A 31 +2T1)4A5
abstract abstract class class 2or0a 2or0a {{ private private int int pos"3 pos"3 pos4; pos4; public abstract void ;; public abstract void dibu5ar() dibu5ar() public public int int 1etPosicion6() 1etPosicion6() {{ return return pos"; pos"; }} ... ... }}
$lase derivada class class %irculo %irculo e"tends e"tends 2or0a 2or0a {{ private private int int radio; radio; public void dibu5ar() public void dibu5ar() $...% ;; $...% ... ... }}
01)12$+A 31 +2T1)4A5
Inter"aces
3eclaracin de un con unto de m(todos abstractos. 1n $,,, son clases abstractas donde todos sus m(todos son abstractos y no eAisten atributos de instancia.
01)12$+A 31 +2T1)4A5
2otacin U6L para interfaces
<<interface>>
Vehculo
INTERFAZ
CLASE ABSTRACTA
Terrestre {abstract}
CLASE ABSTRACTA
Areo
Coche
Bicicleta
Avin
Helicptero
CLASES CONCRETAS
01)12$+A 31 +2T1)4A5
Inter"aces en Java
inter&ace inter&ace 2or0a 2or0a {{ // // 77 8in 8in atributos atributos de de instancia instancia // 7 89lo constantes est:ticas // 7 89lo constantes est:ticas // // 77 $odos $odos los los 0)todos 0)todos son son abstractos abstractos por por de;inici9n de;inici9n void dibu5ar() ; void dibu5ar(); int int 1etPosicion6(); 1etPosicion6(); ... ... }} class class %irculo %irculo i'ple'ents i'ple'ents 2or0a 2or0a {{ private private int int pos"3 pos"3 pos4; pos4; private int radio; private int radio; public public void void dibu5ar() dibu5ar() {...}; {...}; public public int int 1etPosicion6() 1etPosicion6() {...}; {...}; }}
01)12$+A 31 +2T1)4A5
Inter"aces en C,,
class 2or0a class 2or0a { { // 7 8in atributos de instancia // 7 8in atributos de instancia // 7 89lo constantes est:ticas // 7 89lo constantes est:ticas // 7 $odos los 0)todos se declaran abstractos // 7 $odos los 0)todos se declaran abstractos public: public: virtual void dibu5ar()"#; virtual void dibu5ar()"#; virtual int 1etPosicion6()"#; virtual int 1etPosicion6()"#; // resto de 0)todos virtuales puros... // resto de 0)todos virtuales puros... } }
class class %irculo %irculo :: public public 2or0a 2or0a // // (erencia (erencia p)blica p)blica {{ private: private: int int pos"3 pos"3 pos4; pos4; int radio; int radio; public: public: void void dibu5ar() dibu5ar() {...} {...} int 1etPosicion6() int 1etPosicion6() {...}; {...}; }}
01)12$+A 31 +2T1)4A5
01)12$+A 31 +2T1)4A5
TCuentaAbstracta
+ TCuentaAbstracta() + TCuentaAbstracta(TCuentaAbstracta) + ~TCuenta() + getNombre() const + getSaldo() const + getInteres() const + setSaldo() + setInteres() +abonarInteresMensual(): void +mostrar() <<friend>> o erator<<(!!!)
+ TCuenta#o$en()
+ TCuenta#o$en(TCuenta#o$en) + ~TCuenta#o$en() + get%dad()" int + set%dad(int)" $oid +abonarInteresMensual(): void +mostrar() <<friend>> o erator<<(!!!)
01)12$+A 31 +2T1)4A5
class class $%uenta>bstracta $%uenta>bstracta {{ protected: protected: ... ... public: public: ... ... virtual virtual void void abonarInteresMensual()"#; abonarInteresMensual()"#; }; }; class class $%uenta&oven: $%uenta&oven: public public $%uenta>bstracta $%uenta>bstracta {{ private: private: int int edad; edad; public: public: ... ... // // ,-P?<-<@$>%,A@ ,-P?<-<@$>%,A@ en en clase clase derivada derivada void abonarInteresMensual() { void abonarInteresMensual(){ //no //no inter)s inter)s si si el el saldo saldo es es in;erior in;erior al al lB0ite lB0ite i; (1et8aldo()/=1====){ i; (1et8aldo()/=1====){ set8aldo(1et8aldo()*(1C1et,nteres()/1 set8aldo(1et8aldo()*(1C1et,nteres()/1 /1==)); /1==)); }} }; }; // si1ue... // si1ue...
01)12$+A 31 +2T1)4A5
DUpcasting a clase abstractaE
$%uenta&oven $%uenta&oven tc5; tc5; '' $%uenta $%uenta tc tc == ($%uenta)tc5; ($%uenta)tc5; ** '' $%uenta* $%uenta* ptc ptc == ($%uenta ($%uenta *) *) &tc5; &tc5; ** '' $%uenta& $%uenta& rtc rtc == ($cuenta ($cuenta &) &) tc5; tc5; ** $%uenta&oven $%uenta&oven tc5; tc5; $%uenta* $%uenta* ptc ptc == &tc5; &tc5; $%uenta& $%uenta& rtc rtc == tc5; tc5;
TComisionista double base& comisi'n& $entas( + TComisionista() + TComisionista(TComisionista )) + ~TComisionista() + setComisi'n() + getComisi'n() const + set*ase() + get*ase() const
int int 0ain(){ 0ain(){ int int tipo; tipo; <0pleado <0pleado *eptr; *eptr; cout..D,ntroduce cout..D,ntroduce tipoE..endl; tipoE..endl; cin//tipo; //1:;i5o3 cin//tipo; //1:;i5o3 co0isionista co0isionista s#itcF (tipo){ s#itcF (tipo){ case case 1: 1: eptr=ne# eptr=ne# 2i5o(); 2i5o(); breaG; breaG; case case :eptr=ne# :eptr=ne# %o0isionista(); %o0isionista(); breaG; breaG; }} eptr7/1et8alario(); eptr7/1et8alario(); delete delete eptr; eptr; }}
Herencia de implementacin
!
Habilidad para que una clase herede parte o toda su implementacin de otra clase. Debe ser utilizada con cuidado.
80
En la herencia existe una tensin entre expansin (adicin de mtodos ms especficos) y contraccin (especializacin o restriccin de la clase padre) Esta tensin est en la base de su poder, y tambin de los problemas asociados con su uso. En general, la redefinicin de mtodos slo debera usarse para hacer las propiedades ms especficas
! !
81
Especializacin
!
La clase derivada es una especializacin de la clase base: aade comportamiento pero no modifica nada
! !
OK!
VentanaDeTexto editar()
82
Especificacin
!
! !
Implementa mtodos no definidos en la clase base (mtodos abstractos o diferidos). No aade ni elimina nada. La clase derivada es una realizacin (o implementacin) de la clase base.
Pila {abstract}
PilaDeEnteros
apila(Object) : void desapila() : Object tope() : Object
OK!
83
Restriccin (limitacin)
Pjaro Volar()
No todo lo de la clase base sirve a la derivada. Hay que redefinir ciertos mtodos para eliminar comportamiento presente en la clase base
Pingino Nadar()
Generalizacin
Ventana Coordenada_x Coordenada_y Mover()
Se extiende el comportamiento de la clase base para obtener un tipo de objeto ms general. Usual cuando no se puede modificar la clase base. Mejor invertir la jerarqua.
85
La implementacin se parece pero semnticamente los conceptos no estn relacionados jerrquicamente (test es-un). INCORRECTA!!!!
86
Herencia de Construccin
!
Tambin llamada Herencia de Implementacin Pura Una clase hereda pate de su funcionalidad de otra, modificando el interfaz heredado La clase derivada no es una especializacin de la clase base (puede que incluso no haya relacin es-un)
! !
No se cumple el principio de sustitucin (ni se pretende) P. ej., una Pila puede construirse a partir de un Array
Array elementoAt(int i) : Object capacidad() : int numElementos() : int
Pila
apila(Object) : void desapila() : Object tope() : Object
87
La herencia privada en C++ implementa un tipo de herencia de construccin que s preserva el principio de sustitucin:
!
El hecho de que Pila herede de Array no es visible para el cdigo que usa la pila (Pila no publica el interfaz de Array).
!
Pila
apila(Object) : void desapila() : Object tope() : Object
88
HERENCIA
Beneficios y costes de la herencia
Beneficios de la Herencia
! ! ! ! ! ! !
Reusabilidad software Comparticin de cdigo Consistencia de interface Construccin de componentes Prototipado rpido Polimorfismo Ocultacin de informacin
[BUDD] 8.8
90
Costes de la Herencia
! ! ! !
Velocidad de ejecucin Tamao del programa Sobrecarga de paso de mensajes Complejidad del programa
[BUDD] 8.9
91
Herencia vs Todo-Parte
!
Herencia es una relacin entre clases, mientras que Agregacin/Composicin es una relacin entre objetos
!
Herencia es menos flexible Donde se detecta una relacin HAS-A no siempre es posible cambiarla por una relacin de herencia. Sin embargo, donde se detecta una relacin de herencia, siempre es posible reformularla para que se convierta en una relacin de composicin.
! ! !
Un programador de C++ es un programador Todo programador de C++ tiene un programador en su interior Todo programador de C++ tiene una vocacin de programar en su interior
93
Herencia vs Todo-Parte
!
Regla del cambio: no se debe usar herencia para describir una relacin IS-A si se prev que los componentes puedan cambiar en tiempo de ejecucin (si preveo que pueda cambiar mi vocacin #).
!
Las relaciones de composicin se establecen entre objetos, y por tanto permiten un cambio ms sencillo del programa.
Regla del polimorfismo: la herencia es apropiada para describir una relacin IS-A cuando las entidades o los componentes de las estructuras de datos del tipo ms general pueden necesitar relacionarse con objetos del tipo ms especializado (e.g. por reuso).
!
94
Herencia (IS-A) y Composicin (HAS-A) son los dos mecanismos ms comunes de reuso de software
!
Ejemplo: construccin del tipo de dato Conjunto a partir de una clase preexistente Lista
class Lista{
public: Lista(); //constructor void add (int el); int firstElement(); int size(); int includes(int el); void remove (int pos);
};
!
Queremos que la nueva clase Conjunto nos permita aadir un valor al conjunto, determinar el nmero de elementos del conjunto y determinar si un valor especfico se encuentra en el conjunto.
96
Un objeto es una encapsulacin de datos y comportamiento. Por tanto, si utilizamos la Composicin estamos diciendo que parte del estado de la nueva estructura de datos es una instancia de una clase ya existente.
class Conjunto{ public: //constructor debe inicializar el objeto Lista Conjunto():losDatos(){}; int size(){return losDatos.size();}; int includes (int el){return losDatos.includes(el);}; //un conjunto no puede contener valor ms de una vez void add (int el){ if (!includes(el)) losDatos.add(el); }; private: Lista losDatos; };
97
La composicin se puede aplicar del mismo modo en cualquier lenguaje OO e incluso en lenguajes no OO.
!
98
Con herencia una clase nueva puede ser declarada como una subclase de una clase existente, lo que provoca que todas las reas de datos y funciones asociadas con la clase original se asocien automticamente con la nueva abstraccin de datos.
class Conjunto : public Lista{ public: Conjunto() : Lista() {}; //un conjunto no puede contener valores repetidos void add (int el){ //refinamiento if (!includes(el)) Lista::add(el); }; };
Implementamos en trminos de clase base (no objeto) ! No existe una lista como dato privado Las operaciones que actan igual en la clase base y en la derivada no deben ser redefinidas (con composicin s).
99
As, las instancias de la nueva abstraccin deberan comportarse de manera similar a las instancias de la clase padre. En nuestro ejemplo, un Conjunto NO ES una Lista.
" En realidad deberamos: " Usar herencia privada " Reescribir todos los mtodos de Conjunto basndo su implementacin en los de Lista.
100
Define ms claramente la interfaz que soporta el nuevo tipo, independientemente de la interfaz del objeto parte.
La composicin slo presupone que el tipo de datos X se utiliza para IMPLEMENTAR la clase C. Es fcil por tanto:
!
Dejar sin implementar los mtodos que, siendo relevantes para X, no lo son para la nueva clase C Reimplementar C utilizando un tipo de datos X distinto sin impacto para los usuarios de la clase C.
101
Requiere menos cdigo. Oferta ms funcionalidad: cualquier nuevo mtodo asociado a la clase base estar inmediatamente disponible para todas sus clases derivadas.
Desventajas
!
Los usuarios pueden manipular la nueva estructura mediante mtodos de la clase base, incluso si stos no son apropiados. Cambiar la base de una clase puede causar muchos problemas a los usuarios de dicha clase.
102
Herencia: un empleado es una persona. Composicin: una persona tiene un domicilio Composicin: una lista tiene un puntero de tipo nodo al nodo que est en cabeza de la lista (tener-un).
Herencia entre empleado y jefe: Un jefe es un empleado Composicin entre empresa y empleado (o empleado y jefe):
! !
Un empresa puede tener una lista de empleados y otra de jefes Por el principio de los subtipos, una empresa puede tener un nica lista donde aparezcan tanto los jefes como empleados.
103