Documentos de Académico
Documentos de Profesional
Documentos de Cultura
POO 3 Herencia 10 11
POO 3 Herencia 10 11
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, 1987)
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
Caracterizan los objetos por su clase Caracterizan los objetos por su comportamiento
Lenguaje 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* d2=&p; d2=&p; // // sustit sustit Dependiente Dependiente d3=p; d3=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 extends extends Dependiente Dependiente {...} {...} Panadero Panadero pp == new new Panadero(); Panadero(); Dependiente d1=p; Dependiente d1=p; // // sustit. sustit.
HERENCIA DE INTERFAZ
Objetivos:
Momento en el que se identifica el fragmento de cdigo a ejecutar asociado a un mensaje (llamada a mtodo) o el objeto concreto asociado a una variable.
Ventaja: FLEXIBILIDAD
Enlace esttico: el tipo de objeto que contiene una variable se determina en tiempo de compilacin.
Circulo c;
Enlace dinmico: el tipo de objeto al que hace referencia una variable no est predefinido, por lo que el sistema gestionar la variable en funcin de la naturaleza real del objeto que referencie durante la ejecucin. Lenguajes como Smalltalk siempre utilizan enlace dinmico con variables.
C++ slo permite enlace dinmico con variables cuando stos son punteros o referencias, y slo dentro de jerarquas de herencia.
Enlace esttico: la eleccin de qu mtodo ser el encargado de responder a un mensaje se realiza en tiempo de compilacin, en funcin del tipo que tena el objeto destino de la llamada en tiempo de compilacin.
TCuentaJoven tcj; TCuenta tc; tc=tcj; // object slicing tc.abonarInteresMensual(); // Enlace esttico: TCuenta::abonarInteresMensual()
Enlace dinmico la eleccin de qu mtodo ser el encargado de responder a un mensaje se realiza en tiempo de ejecucin, en funcin del tipo correspondiente al objeto que referencia la variable mediante la que se invoca al mtodo en el instante de la ejecucin del mensaje.
Se pretende invocar a ciertos mtodos sobreescritos desde referencias a objetos de la clase base (aprovechando el principio de sustitucin).
En muchos lenguajes OO este rasgo es soportado de forma natural: Por ejemplo, en Java, los mtodos son virtuales por defecto. En C++ para que esto sea posible:
El mtodo debe ser declarado en la clase base como mtodo virtual (mediante la palabra clave virtual). Esto indica que tiene enlace dinmico. La clase derivada debe proporcionar su propia implementacin del mtodo.
class class TCuenta TCuenta {{ ... ... virtual virtual ~TCuenta(); ~TCuenta(); }; }; delete tc; // Qu destructor se invoca? ~TCuentaJoven()
En resumen, si una clase tiene mtodos virtuales Es posible utilizar el principio de sustitucin. Heredar de ella y sobreescribir los mtodos virtuales Para destruir objetos derivados desde punteros a clase base, el destructor de esta clase base debe declararse como mtodo virtual.
Alguno de sus mtodos no est definido: son mtodos abstractos No se pueden crear objetos de estas clases. S se pueden crear referencias (o punteros) a objeto de una clase abstracta (que apuntarn a objetos de clases derivadas)
Propsito: Garantizar que las clases derivadas proporcionan una implementacin propia de ciertos mtodos. Se garantiza el principio de sustitucin.
HERENCIA DE INTERFAZ
Clases abstractas
Las clases que deriven de clases abstractas (o interfaces) deben implementar todos los mtodos abstractos (o sern a su vez abstractas). La clase derivada implementa el interfaz de la clase abstracta.
HERENCIA DE INTERFAZ
Notacin UML para clases abstractas
Vehculo
CLASE ABSTRACTA
CLASE ABSTRACTA
Terrestre {abstract}
CLASE ABSTRACTA
Areo
Coche
Bicicleta
Avin
Helicptero
CLASES CONCRETAS
HERENCIA DE INTERFAZ
HERENCIA DE INTERFAZ
abstract abstract class class Forma Forma {{ private private int int posx, posx, posy; posy; public abstract void ;; public abstract void dibujar() dibujar() public public int int getPosicionX() getPosicionX() {{ return return posx; posx; }} ... ... }}
Clase derivada class class Circulo Circulo extends extends Forma Forma {{ private private int int radio; radio; public void dibujar() public void dibujar() {...} ;; {...} ... ... }}
HERENCIA DE INTERFAZ
Interfaces
Declaracin de un conjunto de mtodos abstractos. En C++, son clases abstractas donde todos sus mtodos son abstractos y no existen atributos de instancia.
HERENCIA DE INTERFAZ
Notacin UML para interfaces
<<interface>>
Vehculo
INTERFAZ
CLASE ABSTRACTA
Terrestre {abstract}
CLASE ABSTRACTA
Areo
Coche
Bicicleta
Avin
Helicptero
CLASES CONCRETAS
HERENCIA DE INTERFAZ
Interfaces en Java
interface interface Forma Forma {{ // // -- Sin Sin atributos atributos de de instancia instancia // Slo constantes estticas // - Slo constantes estticas // // -- Todos Todos los los mtodos mtodos son son abstractos abstractos por por definicin definicin void dibujar() ; void dibujar(); int int getPosicionX(); getPosicionX(); ... ... }} class class Circulo Circulo implements implements Forma Forma {{ private private int int posx, posx, posy; posy; private int radio; private int radio; public public void void dibujar() dibujar() {...}; {...}; public public int int getPosicionX() getPosicionX() {...}; {...}; }}
HERENCIA DE INTERFAZ
Interfaces en C++
class Forma class Forma { { // - Sin atributos de instancia // - Sin atributos de instancia // - Slo constantes estticas // - Slo constantes estticas // - Todos los mtodos se declaran abstractos // - Todos los mtodos se declaran abstractos public: public: virtual void dibujar()=0; virtual void dibujar()=0; virtual int getPosicionX()=0; virtual int getPosicionX()=0; // resto de mtodos virtuales puros... // resto de mtodos virtuales puros... } }
class class Circulo Circulo :: public public Forma Forma // // Herencia Herencia pblica pblica {{ private: private: int int posx, posx, posy; posy; int radio; int radio; public: public: void void dibujar() dibujar() {...} {...} int getPosicionX() int getPosicionX() {...}; {...}; }}
HERENCIA DE INTERFAZ
compareTo(Comparable) : int
HERENCIA DE INTERFAZ
TCuentaAbstracta
+ TCuentaAbstracta() + TCuentaAbstracta(TCuentaAbstracta) + ~TCuenta() + getNombre() const + getSaldo() const + getInteres() const + setSaldo() + setInteres() +abonarInteresMensual(): void +mostrar() <<friend>> operator<<(...)
+ TCuentaJoven()
+ TCuentaJoven(TCuentaJoven) + ~TCuentaJoven() + getEdad(): int + setEdad(int): void +abonarInteresMensual(): void +mostrar() <<friend>> operator<<(...)
HERENCIA DE INTERFAZ
class class TCuentaAbstracta TCuentaAbstracta {{ protected: protected: ... ... public: public: ... ... virtual virtual void void abonarInteresMensual()=0; abonarInteresMensual()=0; }; }; class class TCuentaJoven: TCuentaJoven: public public TCuentaAbstracta TCuentaAbstracta {{ private: private: int int edad; edad; public: public: ... ... // // IMPLEMENTACION IMPLEMENTACION en en clase clase derivada derivada void abonarInteresMensual() { void abonarInteresMensual(){ //no //no inters inters si si el el saldo saldo es es inferior inferior al al lmite lmite if (getSaldo()>=10000){ if (getSaldo()>=10000){ setSaldo(getSaldo()*(1+getInteres()/12/100)); setSaldo(getSaldo()*(1+getInteres()/12/100)); }} }; }; // sigue... // sigue...
HERENCIA DE INTERFAZ
Upcasting a clase abstracta?
TCuentaJoven TCuentaJoven tcj; tcj; TCuenta TCuenta tc tc == (TCuenta)tcj; (TCuenta)tcj; ?? TCuenta* TCuenta* ptc ptc == (TCuenta (TCuenta *) *) &tcj; &tcj; ?? TCuenta& TCuenta& rtc rtc == (Tcuenta (Tcuenta &) &) tcj; tcj; ?? TCuentaJoven TCuentaJoven tcj; tcj; TCuenta* TCuenta* ptc ptc == &tcj; &tcj; TCuenta& TCuenta& rtc rtc == tcj; tcj;
TComisionista double base, comisin, ventas; + TComisionista() + TComisionista(TComisionista &) + ~TComisionista() + setComisin() + getComisin() const + setBase() + getBase() const
int int main(){ main(){ int int tipo; tipo; Empleado Empleado *eptr; *eptr; cout<<Introduce cout<<Introduce tipo<<endl; tipo<<endl; cin>>tipo; //1:fijo, cin>>tipo; //1:fijo, 22 comisionista comisionista switch (tipo){ switch (tipo){ case case 1: 1: eptr=new eptr=new Fijo(); Fijo(); break; break; case case 2:eptr=new 2:eptr=new Comisionista(); Comisionista(); break; break; }} eptr->getSalario(); eptr->getSalario(); 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