Sie sind auf Seite 1von 13

4.4 Variables polimrficas (plantillas): definicin, uso y aplicaciones.

Variables polimrficas En Java, las variables que contienen objetos son variables polimrficas. El trmino polimrfico (literalmente: muchas formas) se refiere al hecho de que una misma variable puede contener objetos de diferentes tipos (del tipo declarado o de cualquier subtipo del tipo declarado). El polimorfismo aparece en los lenguajes orientados a objetos en numerosos contextos, las variables polimrficas constituyen justamente un primer ejemplo. Observemos la manera en que el uso de una variable polimrfica nos ayuda a simplificar nuestro mtodo listar. El cuerpo de este mtodo es for (Elemento elemento : elementos) elemento.imprimir(); En este mtodo recorremos la lista de elementos (contenida en un ArrayList mediante la variable elementos), tomamos cada elemento de la lista y luego invocamos su mtodo imprimir. Observe que los elementos que tomamos de la lista son de tipo CD o DVD pero no son de tipo Elemento. Sin embargo, podemos asignarlos a la variable elemento (declarada de tipo Elemento) porque son variables polimrficas. La variable elemento es capaz de contener tanto objetos CD como objetos DVD porque estos son subtipos de Elemento. Por lo tanto, el uso de herencia en este ejemplo ha eliminado la necesidad de escribir dos ciclos en el mtodo listar. La herencia evita la duplicacin de cdigo no slo en las clases servidoras sino tambin en las clases clientes de aquellas. Nota: Si UD. codifica lo que estamos detallando descubrir que el mtodo imprimir tiene un problema: no imprime todos los detalles. Esto es as porque estamos invocando el mtodo imprimir() de la clase Elemento, que no imprime atributos de CD o DVD.

Enmascaramiento de tipos (Casting)


Algunas veces, la regla de que no puede asignarse un supertipo a un subtipo es ms restrictiva de lo necesario. Si sabemos que la variable de un cierto supertipo contiene un objeto de un subtipo, podra realmente permitirse la asignacin. Por ejemplo: Vehiculo v; Coche a = new Coche(); v = a; // Sin problemas a = v; // Error, segn el compilador Obtendremos un error de compilacin en a = v. El compilador no acepta esta asignacin porque como a (Coche) tiene mas atributos que v (Vehculo) partes del objeto a quedan sin asignacin. El compilador no sabe que v ha sido anteriormente asignado por un coche. Podemos resolver este problema diciendo explcitamente al sistema, que la variable v contiene un objeto Coche, y lo hacemos utilizando el operador de enmascaramiento de tipos, en una operacin tambin conocida como casting. a = (Coche)v; // correcto En tiempo de ejecucin, el Java verificar si realmente v es un Coche. Si fuimos cuidadosos, todo estar bien; si el objeto almacenado en v es de otro tipo, el sistema indicar un error en tiempo de ejecucin (denominado ClassCastException) y el programa se detendr. El compilador no detecta (Naturalmente) errores de enmascaramiento en tiempo de compilacin. Se detectan en ejecucin y esto no es bueno. El enmascaramiento debiera evitarse siempre que sea posible, porque puede llevar a errores en tiempo de ejecucin y esto es algo que claramente no queremos. El compilador no puede ayudamos a asegurar la correccin de este caso. En la prctica, raramente se necesita del enmascaramiento en un programa orientado a objetos bien estructurado. En la mayora de los casos, cuando se use un enmascaramiento en el cdigo,

debiera reestructurarse el cdigo para evitar el enmascaramiento, y se terminar con un programa mejor diseado. Generalmente, se resuelve el problema de la presencia de un enmascaramiento reemplazndolo por un mtodo polimrfico (Un poquito de paciencia).

La clase Object
Todas las clases tienen una superclase. Hasta ahora, nos puede haber parecido que la mayora de las clases con que hemos trabajado no tienen una superclase, excepto clases como DVD y CD que extienden otra clase. En realidad, mientras que podemos declarar una superclase explcita para una clase dada, todas las clases que no tienen una declaracin explcita de superclase derivan implcitamente de una clase de nombre Object. Object es una clase de la biblioteca estndar de Java que sirve como superclase para todos los objetos. Es la nica clase de Java sin superclase. Escribir una declaracin de clase como la siguiente public class Person{} es equivalente a public class Person extends Object{}
Tener una superclase sirve a dos propsitos.

. Podemos declarar variables polimrficas de tipo Object que pueden contener cualquier objeto (esto no es importante) . Podemos usar Polimorfismo (Ya lo vemos) y esto si es importante.

Autoboxing y clases envoltorio


Hemos visto que, con una parametrizacin adecuada, las colecciones pueden almacenar objetos de cualquier tipo; queda un problema, Java tiene algunos tipos que no son objetos. Como sabemos, los tipos primitivos tales como int, boolean y char estn separados de los tipos objeto. Sus valores no son instancias de clases y no derivan de la clase Object. Debido a esto, no son suptipos de Object y normalmente, no es posible ubicarlos dentro de una coleccin. Este es un inconveniente pues existen situaciones en las que quisiramos crear, por ejemplo, una lista de enteros (int) o un conjunto de caracteres (char). Qu hacer? La solucin de Java para este problema son las clases envoltorio. En Java, cada tipo simple o primitivo tiene su correspondiente clase envoltorio que representa el mismo tipo pero que, en realidad, es un tipo objeto. Por ejemplo, la clase envoltorio para el tipo simple int es la clase de nombre Integer. La siguiente sentencia envuelve explcitamente el valor de la variable ix de tipoprimitivo int, en un objeto Integer: Integer ienvuelto = new Integer(ix); y ahora ienvuelto puede almacenarse fcilmente por ejemplo, en una coleccin de tipo ArrayList<Integer>. Sin embargo, el almacenamiento de valores primitivos en un objeto coleccin se lleva a cabo an ms fcilmente mediante una caracterstica del compilador conocida como autoboxing. En cualquier lugar en el que se use un valor de un tipo primitivo en un contexto que requiere un tipo objeto, el compilador automticamente envuelve al valor de tipo primitivo en un objeto con el envoltorio adecuado. Esto quiere decir que los valores de tipos primitivos se pueden agregar directamente a una coleccin: private ArrayList<Integer> listaDeMarcas; public void almacenarMarcaEnLista (int marca){ listaDeMarcas.agregar(marca); }

La operacin inversa, unboxing, tambin se lleva a cabo automticamente, de modo que el acceso a un elemento de una coleccin podra ser: int primerMarca = listaDeMarcas.remove(0); El proceso de autoboxing se aplica en cualquier lugar en el que se pase como parmetro un tipo primitivo a un mtodo que espera un tipo envoltorio, y cuando un valor primitivo se almacena en una variable de su correspondiente tipo envoltorio. De manera similar, el proceso de unboxing se aplica cuando un valor de tipo envoltorio se pasa como parmetro a un mtodo que espera un valor de tipo primitivo, y cuando se almacena en una variable de tipo primitivo.

Tipo esttico y tipo dinmico


Volvemos sobre un problema inconcluso: el mtodo imprimir de DoME, no muestra todos los datos de los elementos. El intento de resolver el problema de desarrollar un mtodo imprimir completo y polimrfico nos conduce a la discusin sobre tipos estticos y tipos dinmicos y sobre despacho de mtodos. Comencemos desde el principio. Necesitamos ver ms de cerca los tipos. Consideremos la siguiente sentencia: Elemento e1 = new CD(); Cul es el tipo de e1? Depende de qu queremos decir con tipo de e1. El tipo de la variable e1 es Elemento; (tipo esttico) el tipo del objeto almacenado en e1 es CD. (tipo dinmico) Entonces el tipo esttico de e1 es Elemento y su tipo dinmico es CD. En el momento de la llamada e1.imprimir(); el tipo esttico de la variable elemento es Elemento mientras que su tipo dinmico puede ser tanto CD como DVD. No sabemos cul es su tipo ya que asumimos que hemos ingresado tanto objetos CD como objetos DVD en nuestra base de datos. Y en que clase debe estar codificado el mtodo imprimir()? En tiempo de compilacin necesitamos de la existencia de imprimir() en la clase Elemento, el compilador trabaja con tipo esttico. En tiempo de ejecucin necesitamos de la existencia de un mtodo imprimir() adecuado a los datos del objeto CD o DVD. En definitiva, necesitamos de imprimir() en las tres clases. Aunque no ser lo mismo lo que se imprima en cada uno de ellos. Lo que debemos hacer entonces es

Sobrescribir el mtodo Veamos el mtodo imprimir en cada una de las clases.


public class Elemento{ public void imprimir(){ System.out.print(titulo + " (" + duracion + " minutos) " ); if (loTengo){System.out.println("*"); } else {System.out.println();} System.out.println(" " + comentario); } } public class CD extends Elemento{ public void imprimir(){ System.out.println(" " + interprete); System.out.println(" temas: " + numeroDeTemas); }

} public class DVD extends Elemento{ public void imprimir(){ System.out.println(" director: " + director); } } Este diseo funciona mejor: compila y puede ser ejecutado, aunque todava no est perfecto. Proporcionamos una implementacin de este diseo mediante el proyecto dome-v3. La tcnica que usamos ac se denomina sobrescritura (algunas veces tambin se hace referencia a esta tcnica como redefinicin). La sobrescritura es una situacin en la que un mtodo est definido en una superclase (en este ejemplo, el mtodo imprimir de la clase Elemento) y un mtodo, con exactamente la misma signatura, est definido en la subclase. En esta situacin, los objetos de la subclase tienen dos mtodos con el mismo nombre y la misma signatura: uno heredado de la superclase y el otro propio de la subclase. Cul de estos dos se ejecutar cuando se invoque este mtodo? Bsqueda dinmica del mtodo (Despacho dinmico) Si ejecutamos el mtodo listar de la BaseDeDatos, podremos ver que se ejecutarn los mtodos imprimir de CD y de DVD pero no el de Elemento, y entonces la mayor parte de la informacin, la comn contenida en Elemento, no se imprime. Que est pasando? Vimos que el compilador insisti en que el mtodo imprimir est en la clase Elemento, no le alcanzaba con que los mtodos estuvieran en las subclases. Este experimento ahora nos muestra que el mtodo de la clase Elemento no se ejecuta para nada, pero s se ejecutan los mtodos de las subclases. Ocurre que el control de tipos que realiza el compilador es sobre el tipo esttico, pero en tiempo de ejecucin los mtodos que se ejecutan son los que corresponden al tipo dinmico. Saber esto es muy importante pero todava insuficiente. Para comprenderla mejor, veamos con ms detalle cmo se invocan los mtodos. Este procedimiento se conoce como bsqueda de mtodo, ligadura de mtodo o despacho de mtodo. En este libro, nosotros usamos la terminologa bsqueda de mtodo. Comenzamos con un caso bien sencillo de bsqueda de mtodo. Suponga que tenemos un objeto de clase DVD almacenado en una variable v1 declarada de tipo DVD (Figura 9.5). La clase DVD tiene un mtodo imprimir y no tiene declarada ninguna superclase. Esta es una situacin muy simple que no involucra herencia ni polimorfismo. Ejecutamos v1.imprimir{). Esto requiere de las siguientes acciones: l. Se accede a la variable v1. 2. Se encuentra el objeto almacenado en esa variable (siguiendo la referencia). 3. Se encuentra la clase del objeto (siguiendo la referencia es instancia de). 4. Se encuentra la implementacin del mtodo imprimir en la clase y se ejecuta. Hasta aqu, todo es muy simple. A continuacin, vemos la bsqueda de un mtodo cuando hay herencia. El escenario es similar al anterior, pero esta vez la clase DVD tiene una superclase, Elemento, y el mtodo imprimir est definido slo en la superclase Ejecutamos la misma sentencia. La invocacin al mtodo comienza de manera similar: se ejecutan nuevamente los pasos 1 al 3 del escenario anterior pero luego contina de manera diferente:

4. No se encuentra ningn mtodo imprimir en la clase DVD. 5. Se busca en la superclase un mtodo que coincida. Y esto se hace hasta encontrarlo, subiendo en la jerarqua hasta Object si fuera necesario. Tenga en cuenta que, en tiempo de ejecucin, debe encontrarse definitivamente un mtodo que coincida, de lo contrario la clase no habra compilado. 6. En nuestro ejemplo, el mtodo imprimir es encontrado en la clase Este ejemplo ilustra la manera en que los objetos heredan los mtodos. Cualquier mtodo que se encuentre en la superclase puede ser invocado sobre un objeto de la subclase y ser correctamente encontrado y ejecutado. Ahora llegamos al escenario ms interesante: la bsqueda de mtodos con una variable polimrfica y un mtodo sobrescrito. Los cambios: . El tipo declarado de la variable v1 ahora es Elemento, no DVD. . El mtodo imprimir est definido en la clase Elemento y redefinido (o sobrescrito) en la clase DVD. Este escenario es el ms importante para comprender el comportamiento de nuestra aplicacin DoME y para encontrar una solucin a nuestro problema con el mtodo imprimir. Los pasos que se siguen para la ejecucin del mtodo son exactamente los mismos pasos 1 al 4, primer caso Observaciones: . No se usa ninguna regla especial para la bsqueda del mtodo en los casos en los que el tipo dinmico no sea igual al tipo esttico. . El mtodo que se encuentra primero y que se ejecuta est determinado por el tipo dinmico, no por el tipo esttico. La instancia con la que estamos trabajando es de la clase DVD, y esto es todo lo que cuenta. Los mtodos sobrescritos en las subclases tienen precedencia sobre los mtodos de las superclases. La bsqueda de mtodo comienza en la clase dinmica de la instancia, esta redefinicin del mtodo es la que se encuentra primero y la que se ejecuta. Esto explica el comportamiento que observamos en nuestro proyecto DoME. Los mtodos imprimir de las subclases (CD y DVD) slo se ejecutan cuando se imprimen los elementos, produciendo listados incompletos. Como podemos solucionarlo?

Llamada a super en mtodos


Ahora que conocemos detalladamente cmo se ejecutan los mtodos sobrescritos podemos comprender la solucin al problema de la impresin. Es fcil ver que lo que queremos lograr es que, para cada llamada al mtodo imprimir de, digamos un objeto CD, se ejecuten para el mismo objeto tanto el mtodo imprimir de la clase Elemento como el de la clase CD. De esta manera se imprimirn todos los detalles. Cuando invoquemos al mtodo imprimir sobre un objeto CD, inicialmente se invocar al

mtodo imprimir de la clase CD. En su primera sentencia, este mtodo se convertir en una invocacin al mtodo imprimir de la superclase que imprime la informacin general del elemento. Cuando el control regrese del mtodo de la superclase, las restantes sentencias del mtodo de la subclase imprimirn los campos distintivos de la clase CD. public void imprimir(){ // Mtodo imprimir de la clase CD super.imprimir(); System.out.println(" " + interprete); System.out.println(" temas: ") + numeroDeTemas); } Detalles sobre diferencias del super usado en constructores: el nombre del mtodo de la superclase est explcitamente establecido. Una llamada a super en un mtodo siempre tiene la forma super.nombre-del-mtodo(parmetros); La llamada a super en los mtodos puede ocurrir en cualquier lugar dentro de dicho mtodo. No tiene por qu ser su primer sentencia. La llamada a super no se genera, es completamente opcional.

Mtodo polimrfico
Lo que hemos discutido en las secciones anteriores, desde Tipo esttico y tipo dinmico hasta ahora, es lo que se conoce como despacho de mtodo polimrfico (o mas simplemente, Polimorfismo). Recuerde que una variable polimrfica es aquella que puede almacenar objetos de diversos tipos (cada variable objeto en lava es potencialmente polimrfica). De manera similar, las llamadas a mtodos en lava son polimrficas dado que ellas pueden invocar diferentes mtodos en diferentes momentos. Por ejemplo, la sentencia elemento.imprimir(); puede invocar al mtodo imprimir de CD en un momento dado y al mtodo imprimir de DVD en otro momento, dependiendo del tipo dinmico de la variable elemento. Bueno, no hay mucho ms por ver en herencia y polimorfismo. Claro que para consolidar esto necesitamos verlo funcionando. Para hacer mas completo el demo de polimorfismo, vamos a incorporar un elemento ms: Libro, que extiende directamente Elemento, sin incorporarle ningn atributo adicional. import java.util.ArrayList; public class BaseDeDatos{ private ArrayList<Elemento> elementos; protected String auxStr; public BaseDeDatos(){ // constructor elementos = new ArrayList<Elemento>(); } public void agregarElemento (Elemento elElemento){ elementos.add(elElemento); } public String toString(){ // Cadena con todos los elementos contenidos auxStr = "Contenidos BaseDeDatos\n"; auxStr+=elementos.toString(); return auxStr; } } package dome; public class Elemento{ private String titulo; private int duracion; private boolean loTengo; private String comentario;

public Elemento(String elTitulo, int tiempo) { titulo = elTitulo; duracion = tiempo; loTengo = false; comentario = ""; } public String toString(){ String aux = titulo + " (" + duracion + " minutos) "; if (loTengo)aux += "*"; aux += " " + comentario+"\n"; return aux; } } package dome; public class CD extends Elemento{ private String interprete; private int numeroDeTemas; public CD(String elTitulo, String elInterprete, int temas, int tiempo) { super(elTitulo, tiempo); interprete = elInterprete; numeroDeTemas = temas; } public String toString(){ String aux = super.toString(); aux+= " interprete (CD): " + interprete+"\n"; aux+= " temas: " + numeroDeTemas+"\n"; return aux; } } package dome; public class DVD extends Elemento{ private String director; public DVD(String elTitulo, String elDirector, int time) { super(elTitulo, time); director = elDirector; } public String toString(){ String aux = super.toString(); aux+= " director (DVD): " + director+"\n"; return aux; } } package dome; public class Libro extends Elemento{ public Libro(String elTitulo, int time){ super(elTitulo, time); } } package dome; // @author Tymoschuk, Jorge public class Main { private BaseDeDatos db; public void DemoBaseDedatos(){ System.out.println("Demo inicia"); db = new BaseDeDatos();

Elemento elem; // Incluyo 2 CDs elem = new CD("Pajaros en la Cabeza","Amaral",14,35); db.agregarElemento(elem); elem = new CD("One chance","Paul Pots",10,30); db.agregarElemento(elem); // Incluyo 2 DVDs elem = new DVD("Soy Leyenda","Francis Lawrence",120); db.agregarElemento(elem); elem = new DVD("Nada es Para Siempre","Robert Redford",105); db.agregarElemento(elem); // Incluyo dos libros elem = new Libro("El Seor de los Anillos",5000); db.agregarElemento(elem); elem = new Libro("El Don Apacible",10000); db.agregarElemento(elem); // veamos que hemos hecho System.out.println(db.toString()); System.out.println("Demo terminado"); } public static void main(String[] args) { Main demo = new Main(); demo.DemoBaseDedatos(); } } La sentencia System.out.println(db.toString()), mtodo public void DemoBaseDedatos() es
la que se ejecuta inicialmente. Esta sentencia: Incorpora en la cadena el resultado de elementos.toString. Como elementos es una instancia de ArrayList, usa el toString() de esta clase (De ah los corchetes de cierre y las comas separadoras). elementos contiene 6 instancias de la variable polimrfica Elemento: las dos primeras tienen tipo dinmico CD. Entonces, en la ejecucin del toString() propio invocan super.toString() (el de Elemento) y luego completan con los datos especficos de CD. Las dos siguientes tienen tipo dinmico DVD. Proceden exactamente lo mismo que CD. Las dos ltimas instancias tienen tipo dinmico Libro. Como no tienen toString() propio, el despacho dinmico encuentra el de Elemnto y este es el que se ejecuta. Complicado o facil? En todo caso, la programacin es muy sinttica, nada de sobreescritura, cada parte del armado de la cadena que imprime System.out.println(db.toString()) lo hace el mtodo del objeto responsable de ello, como manda la POO.

4.5 Reutilizacin de cdigo.

Lo primero que se les viene a la cabeza a los estudiantes (y a muchos profesionales) cuando se les menciona la reutilizacin del cdigo es el famoso copiar y pegar al que se han acostumbrado en la programacin estructurada, y de echo muchos lo hacen en poo, lo cual es una de las practicas que ms encarece el desarrollo de software. Como todo en Java, el problema se resuelve con las clases. Para reutilizar el cdigo creamos nuevas clases pero, en lugar de partir de

cero, partimos de clases, relacionadas con nuestra clase, que han sido ya creadas y depuradas. El truco est en usar las clases sin ensuciar el cdigo existente. Una forma de hacer esto es crear objetos de nuestras clases existentes dentro de la nueva clase. Esto se conoce como composicin porque la nueva clase est compuesta de objetos de clases existentes. Estamos reutilizando la funcionalidad del cdigo, y no la forma.

Otra forma es crear una nueva clase como un tipo de una clase ya existente. Tomamos la forma de la clase existente y aadimos cdigo a la nueva, sin modificar la clase existente. Esta forma de crear nuevos objetos se llamada herencia, y lo que hacemos es extender la clase en la que nos basamos para crear la nueva.

Composicin:
Hasta ahora hemos usado la composicin de cierta manera, ej. cuando hacemos una interfaz grfica de usuario, nuestra clase de interfaz grfica esta compuesta por un frame, unos panel, botones, etc. todos estos objetos componen el objeto de interfaz grfica. Es decir que la composicin consiste en poner manejadores de objetos dentro de nuestra clase, estos manejadores de objetos no sern otra cosa que instancias de las clases en las que nos estamos basando para crear la nueva clase.

Recordemos que la forma para determinar cuando usar composicin es cuando podemos decir que nuestra nueva clase tiene un elemento de otro tipo de objetos, por ejemplo un cronmetro tiene: horas, minutos y segundos, es decir que una clase Cronometro esta compuesta por otras clases llamadas: Horas, Minutos Veamos como seria esta clase:
public Horas class Cronometro { h;

Segundos.

Minutos Segundos

m; s;

String int

cadena; seg,min,hor;

public seg=0; min=0; hor=0; h m s cadena } = = = = new

Cronometro()

new new new String("0 : 0

Horas(); Minutos(); Segundos(); : 0");

public seg if(seg==0){ min=m.forward(); if(min==0){ hor=h.forward(); } } cadena return } = hor + "

String =

avanzar(){ s.forward();

"

min

"

"

seg;

cadena;

public seg min hor cadena = hor + " :

String = = = " + min + " : "

reset(){ s.reset(); m.reset(); h.reset(); + seg;

return } }

cadena;

Nuestra clase Cronometro est compuesta entre otras cosas por objetos del tipo Horas, Minutos y Segundos y a travs del constructor de nuestra clase creamos las instancias de cada una de ellas.

Herencia:
En java aunque no establezcamos de manera explicita la herencia siempre est presente, ya que todas las clases que creemos heredan de la clase Object, por eso es valido decir que en java todo es un objeto. La sintaxis para la composicin es obvia pero, para realizar la herencia, hay una forma claramente distinta. Cuando heredamos, estamos diciendo "Esta nueva clase es como esa clase antigua", por ejemplo es decir que la clase Horas es una UnidadDeTiempo. Afirmamos esto en el cdigo dando el nombre de la clase como siempre pero, antes de la apertura del lmite cuerpo de clase, pondremos la palabra clave "extends" seguida por el nombre de la clase base. Cuando hagamos esto, obtendremos automticamente todos los datos miembros y mtodos de la clase base. Primero veamos como seria la clase UnidadDeTiempo:

public int int

class

UnidadDeTiempo

{ valor; tope;

public if(valor valor=0; else valor++;

int ==

forward(){ tope)

return }

valor;

public valor=0; return } }

int

reset(){

valor;

Y nuestra clase Horas:

public public

class

Horas

extends Horas()

UnidadDeTiempo{ {

this.valor=0; this.tope=23; } }

De esta manera sin necesidad de tener que escribir nuevamente todos el cdigo de UnidadDeTiempo lo tememos disponible en la clase Horas, pero que partes tenemos disponibles?, todos los atributos y los mtodos de la clase padre estn disponibles en la clase hija pero dependiendo de los modificadores de acceso o visibilidad de estos, por ejemplo los atributos y mtodos de tipo friendly solo estarn disponibles para las clases hijas que heredan de una clase padre en el mismo paquete, los atributos y mtodos de tipo public estarn disponibles para todas las clases que hereden de la clase padre sin importar que se halle o no en el mismo paquete; los miembros protected tambin son accesibles desde las clases hijas. El cdigo de nuestra clases hijas no tienen porque limitarse solo al cdigo heredado, de hecho casi siempre la herencia se hace para extender la funcionalidad de las clases heredadas aadiendo nuevos mtodos y atributos.

La

composicin

la

herencia:

Tanto la composicin como la herencia permiten poner sub-objetos dentro de tu nueva clase. Podramos preguntarnos cul es la diferencia entre los dos, y cundo elegir uno en lugar del otro. La composicin es generalmente usada cuando deseamos las caractersticas de una clase existente dentro de una nueva clase, pero no su interfaz. Es decir, ponemos un para poder usarlo para implementar caractersticas de nuestra nueva clase, pero el usuario de esa nueva clase ver el interfaz que hemos definido en lugar del interfaz del objeto insertado. Los objetos miembros usan la implementacin ocultndose a s mismos, por lo que esto es una cosa segura a hacer y, cuando el usuario sabe que estamos uniendo un conjunto de partes, hace que el interfaz sea ms fcil de entender. Cuando heredamos, estamos cogiendo una clase existente y creando una versin especial de esa clase. En general, esto significa que estamos tomando una clase de propsito general, especializndola para un caso o necesidad particular. Pensando un poco, podr entender que no tendra sentido construir un coche usando un objeto vehculo (un coche no contiene un vehculo, es un vehculo!). La relacin es- un viene expresada por la herencia, y la relacin tiene un viene expresada por la composicin.