Vous êtes sur la page 1sur 25

UNMSM Anlisis y Diseo de Algoritmos

Relaciones entre clases: herencia y realizacin


Hasta este punto conocemos varios tipos de relaciones:

La DEPENDENCIA, que indica que un objeto de una clase hace uso de


otro objeto de una clase, slo de forma momentnea. Se representa
en cdigo como un parmetro recibido por un mtodo o tambin por
un objeto que est siendo instanciado dentro de algn mtodo.

La ASOCIACIN, que indica que un objeto de una clase hace uso de


otro objeto de una clase, de forma ms permanente. Se representa en
cdigo como un atributo de una clase.

La AGREGACIN, que indica como un objeto de una clase es la


PARTE de otro objeto de una clase, conocida como el TODO,
adems si el TODO fuese destruido, las PARTES no sern
necesariamente destruidas. Al tratarse de un subtipo de la relacin de
ASOCIACIN se representa en cdigo como un atributo de una clase,
adems opcionalmente podemos agregarle los mtodos add, get y
remove para agregar, obtener y eliminar los objetos PARTE
respectivamente.

La COMPOSICIN, que es exactamente igual a la AGREGACIN, con la


diferencia de que al destruir el TODO necesariamente las PARTES
tambin son destruidas.

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

Ahora para finalizar con el estudio de las relaciones en la POO, veremos la


HERENCIA y la REALIZACIN.

Relacin de HERENCIA
Definicin
La herencia es una propiedad de la POO que permite que las clases hereden
los atributos y los mtodos de otras clases.

Notacin
Se representa con una lnea slida, que va desde una clase (llamada "HIJA")
haca otra clase, con un tringulo al final (llamada "PADRE")

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

Formas de lectura

"La clase A hereda de la clase B"

"La clase A es hija de la clase B"

"La clase B es padre de la clase A"

Forma de implementacin
En Java se logra por medio de la palabra reservada "extends" y otorgndoles
una visibilidad de protected a los atributos y mtodos.

Ejemplo
Imaginemos que estamos realizando un programa informtico para un
colegio y necesitamos crear las clases Alumno y Profesor, en UML
podemos hacer lo siguiente:

Vemos que hay varios atributos y mtodos que se repiten, con ellos podemos
crear una tercera clase llamada Persona:

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

Esta clase Persona rene los atributos y mtodos comunes a las clases
Alumno y Profesor. Por ltimo slo falta agregar la relacin de HERENCIA
entre las clases:

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

De esta manera hacemos que la clase ALUMNO herede todos los mtodos
y atributos de la clase PERSONA, lo mismo para la clase PROFESOR.

Ahora veamos la implementacin en Java:

Clase Persona.java
public class Persona{
protected String nombres;
protected String apellidos;
protected int edad;
public Persona(){
}
public String getNombres() {
return nombres;
}
public void setNombres(String nombres) {
this.nombres = nombres;
}
public String getApellidos() {
return apellidos;
}
public void setApellidos(String apellidos) {
this.apellidos = apellidos;
}
public int getEdad() {
return edad;
}
public void setEdad(int edad) {
this.edad = edad;
}
}

Clase Alumno.java
public class Alumno extends Persona{

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos


private int grado;
public Alumno(){
}
public int getGrado() {
return grado;
}
public void setGrado(int grado) {
this.grado = grado;
}
}

Clase Profesor.java
public class Profesor extends Persona{
private String dni;
public Profesor(){
}
public String getDni() {
return dni;
}
public void setDni(String dni) {
this.dni = dni;
}
}

Para realizar la herencia en las clases Alumno y Profesor estamos usando


la palabra reservada extends seguido por el nombre de la clase de la cual
heredamos, en este caso Persona.

Tambin, en la clase padre Persona los atributos no tienen una visibilidad


de private, sino una de protected, de esta manera las clases hijas pueden
acceder a estos atributos, ya que si fueran private no podran usarlos.

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

Podemos probar nuestras clases en el main:

Clase Programa.java
public class Programa{
public static void main(String[] args){
/*Creamos una alumno y un profesor*/
Alumno alumno = new Alumno();
Profesor profesor = new Profesor();
/*Les colocamos un nombre*/
alumno.setNombres("Juan Luis");
profesor.setNombres("Marco Aurelio");
/*Los mostramos en pantalla*/
System.out.println("Alumno: "+alumno.getNombres());
System.out.println("Profesor: "+profesor.getNombres());
/*Tambin es posible crear un objeto de la clase padre*/
Persona unaPersona = new Persona();
unaPersona.setNombres("Mark Twain");
System.out.println("Una persona: "+unaPersona.getNombres());
}
}

De esta manera podemos crear un alumno y un profesor para luego usar los
mtodos heredados desde la clase Persona. Tambin, si as lo quisiramos,
podemos crear un objeto de la clase Persona como si se tratase de una
clase cualquiera.

Los constructores en la herencia

En nuestro ejemplo anterior agregumosles un constructor ms a nuestras


clases, que reciba como parmetro el nombre:

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

Clase Persona.java
public class Persona{
protected String nombres;
protected String apellidos;
protected int edad;
public Persona(){
}
public Persona(String nombres){
this.nombres = nombres;
}
public String getNombres() {
return nombres;
}
public void setNombres(String nombres) {
this.nombres = nombres;
}
public String getApellidos() {
return apellidos;
}
public void setApellidos(String apellidos) {
this.apellidos = apellidos;
}
public int getEdad() {
return edad;
}
public void setEdad(int edad) {
this.edad = edad;
}
}

Clase Alumno.java
public class Alumno extends Persona{
private int grado;
public Alumno(){
}

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

public Alumno(String nombres) {


}
public int getGrado() {
return grado;
}
public void setGrado(int grado) {
this.grado = grado;
}
}

Clase Profesor.java
public class Profesor extends Persona{
private String dni;
public Profesor(){
}
public Profesor(String nombres){
}
public String getDni() {
return dni;
}
public void setDni(String dni) {
this.dni = dni;
}
}

Y en nuestro main colocamos:

Clase Programa.java
public class Programa{
public static void main(String[] args){
/*Creamos una alumno y un profesor*/
Alumno alumno = new Alumno("Juan Luis");
Profesor profesor = new Profesor("Marco Aurelio");

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

/*Los mostramos en pantalla*/


System.out.println("Alumno: "+alumno.getNombres());
System.out.println("Profesor: "+profesor.getNombres());
}
}

Si ejecutamos todo esto, obtenemos como salida:

Salida:
Alumno: null
Profesor: null

Por qu obtuvimos este resultado?, pues porque los constructores que


estamos usando de Alumno y Profesor estn sin una implementacin:

Constructor de la clase Alumno


public Alumno(String nombres){
}

Constructor de la clase Profesor


public Profesor(String nombres){
}

Sin embargo el constructor de la clase padre Persona si tiene la


implementacin:

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

Constructor de la clase Persona


public Persona(String nombres){
this.nombres = nombres;
}

Para hacer referencia al constructor de la clase padre a la clase hija debemos


de usar la palabra reservada super, que representa al constructor de la
clase padre, y dentro de ella enviarle los parmetros de construccin:

Constructor de la clase Alumno


public Alumno(String nombres){
super(nombres);
}

Constructor de la clase Profesor


public Profesor(String nombres){
super(nombres);
}

De esta manera estamos llamando al constructor de la clase padre desde la


clase hija.

Referenciando a clases hijas con las clases padre

Gracias a la herencia es posible referenciar a las clases hijas con las clases
padres. Veamos el siguiente cdigo en Java que hace uso de las clases
Alumno, Profesor y Persona vistos antes:

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

Clase Programa.java
public class Programa{
public static void main(String[] args){
Persona persona = new Alumno();
persona.setNombres("Juan Pablo");
Alumno alumno = (Alumno) persona;
alumno.setGrado(3);
System.out.println("Nombre (desde persona): "+persona.getNombres());
System.out.println("Nombre (desde alumno): "+alumno.getNombres());
System.out.println("Grado: "+alumno.getGrado());
}
}

Vemos que una variable llamada persona que es del tipo Persona est
siendo instanciada como un tipo Alumno. Esto es posible porque la clase
padre de Alumno es Persona.

Sin embargo, slo podremos acceder a los atributos y mtodos de la clase


Persona desde la variable persona. Si quisiramos acceder a los atributos
y mtodos de la clase Alumno primero debemos de realizar un casting de
la variable persona para convertirla a una variable del tipo Alumno. Slo
as podemos acceder a los atributos y mtodos de la clase Alumno.

Hay que tener en cuenta que el casting que realicemos debe ser vlido. Por
ejemplo, lo siguiente producira un error:

Clase Programa.java
public class Programa{
public static void main(String[] args){

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

Persona persona = new Alumno();


persona.setNombres("Juan Pablo");
Profesor profesor = (Profesor) persona;
profesor.setDni("12345678");
System.out.println("Nombre (desde persona): "+persona.getNombres());
System.out.println("Nombre (desde alumno): "+profesor.getNombres());
System.out.println("Grado: "+profesor.getDni());
}
}

El origen de error se debe a que la variable persona fue instanciada como


un objeto de la clase Alumno, y en el casting estamos convirtindola a una
variable del tipo Profesor. Esto es incorrecto, el casting debe realizarse al
tipo de dato con el que fue instanciado.

En todo caso, Java nos da una herramienta para averiguar la instancia con la
cual fue construido un objeto gracias a la palabra reservada instanceof:

Clase Programa.java
public class Programa{
public static void main(String[] args){
Persona persona = new Alumno();
persona.setNombres("Juan Pablo");
if(persona instanceof Alumno){
System.out.println("Se instanci como Alumno");
}else{
if(persona instanceof Profesor){
System.out.println("Se instanci como Profesor");
}
}
}
}

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

Aqu estamos preguntado si la variable persona es una instancia de la clase


Alumno, o si la variable persona es una instancia de la clase Profesor

Jerarqua de herencia

Es posible formar jerarquas de herencia entre las clases. Por ejemplo, si


tenemos a la clase A, B y C podemos relacionarlas de la siguiente
manera:

En este caso C hereda de B, y a su vez B hereda de A, por lo tanto por


transitividad C hereda de A.

Herencia mltiple

En la vida real podemos encontrarnos con muchos escenarios en donde una


clase debe de heredar no slo de una, sino de varias clases, por ejemplo si
estamos modelando un vehculo anfibio que vaya tanto por tierra como agua
podemos crear el siguiente diagrama:

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

VehiculoTerrestre

VehiculoAcuatico

VehiculoAnfibio

En este caso la clase VehiculoAnfibio hereda de VehiculoTerrestre y


VehiculoAcuatico.

Cmo podemos implementar esta herencia mltiple en Java?, la respuesta


es que no se puede. En Java no se permite la herencia mltiple, una clase
slo puede heredar a lo ms de otra clase, no de dos o ms.

De todas maneras aunque no sea posible implementar la herencia mltiple


en Java existen formas de emularla, pero antes de aprenderla debemos de
ver el ltimo tipo de relacin que estudiaremos: la REALIZACIN.

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

Relacin de REALIZACIN
Definicin
La herencia es una relacin de la POO que permite definir el comportamiento
de una clase sin la necesidad de implementar los mtodos: define el qu,
no el cmo.

Notacin
Se representa con una lnea punteada, que va desde una clase haca una
interfaz, con un tringulo al final.

Interfaz

Clase

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

Formas de lectura

"La clase A implementa la interfaz B"

"La interfaz B define la clase A"

Forma de implementacin
En Java definimos una interfaz por medio de la palabra reservada interface,
y la implementamos en una clase por medio de la palabra reservada
implements.

Ejemplo
Supongamos que una fbrica especializada en la fabricacin de calculadoras
nos contrata para desarrollar su software. La fbrica produce calculadoras de
dos tipos: comunes y cientficas. Tambin nos dicen que las calculadoras
comunes pueden sumar, restar, multiplicar y dividir, mientras que las
cientficas adems de esas operaciones pueden obtener el seno, el coseno y
la tangente. Por ltimo nos informan que las calculadoras cientficas al
tratarse de aparatos usados para clculos avanzados deben implementar los
algoritmos de clculos de la forma ms eficiente posible.

En este problema vemos claramente que hay dos tipos de calculadora,


adems se nos menciona que ambos comparten operaciones iguales pero
que tienen implementaciones diferentes (las calculadoras cientficas tienen
implementado un algoritmo de clculo ms eficiente). Este es el escenario
perfecto para el uso de interfaces.

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

En este caso definimos los cuatro mtodos comunes en la interfaz, y


agregamos los mtodos propios a la calculadora cientfica.

Su implementacin en Java es como sigue:

Interfaz Calculadora.java
public interface Calculadora {
public
public
public
public

double
double
double
double

sumar(double a, double b);


restar(double a, double b);
multiplicar(double a, double b);
dividir(double a, double b);

Clase CalculadoraComun.java
public class CalculadoraComun implements Calculadora{
public double sumar(double a, double b) {
System.out.println("Algoritmo comn de suma");

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos


return a+b;
}
public double restar(double a, double b) {
System.out.println("Algoritmo comn de resta");
return a-b;
}
public double multiplicar(double a, double b) {
System.out.println("Algoritmo comn de multiplicacin");
return a*b;
}
public double dividir(double a, double b) {
System.out.println("Algoritmo comn de divisin");
return a/b;
}
}

Clase CalculadoraCientifica.java
public class CalculadoraCientifica implements Calculadora{
/*Mtodos implementados*/
public double sumar(double a, double b) {
System.out.println("Algoritmo comn de suma");
return a+b;
}
public double restar(double a, double b) {
System.out.println("Algoritmo comn de resta");
return a-b;
}
public double multiplicar(double a, double b) {
System.out.println("Algoritmo comn de multiplicacin");
return a*b;
}
public double dividir(double a, double b) {
System.out.println("Algoritmo comn de divisin");
return a/b;
}
/*Mtodos propios*/
public double seno(double a){
return Math.sin(a);
}
public double coseno(double a){
return Math.cos(a);
}

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

public double tangente(double a){


return Math.tan(a);
}
}

Como se puede observar, hemos declarado la interfaz Calculadora gracias a


la palabra reservada interface, y hemos implementado esta interfaz en dos
clases diferentes, en donde cada una de ellas tiene su propia
implementacin.

Pero por qu no usamos la herencia?, pues porque con la herencia la


interfaz Calculadora hubiese tenido que ser no una interfaz, sino una clase
que ya implemente los mtodos, si hubiese sido as ambos tipos de
calculadora hubiesen tenido la misma implementacin y no se hubiese
podido implementar los mtodos optimizados para la calculadora cientfica.

Siempre debemos implementar los mtodos de las interfaces?


Cuando una clase implementa una interfaz necesariamente debe de
implementar todos los mtodos que la interfaz defina, incluso esta
implementacin puede ser vaca, pero todos deben de ser implementados.

Por ejemplo si tenemos la siguiente interfaz:

Interfaz Dibujante.java
public interface Dibujante {
public void dibujarCuadrado();
public void dibujarCirculo();
public void dibujarRectangulo();

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos


public void dibujarFiguraHumana();
}

Clase DibujantePrincipiante.java
public class DibujantePrincipiante implements Dibujante{
public void dibujarCuadrado() {
System.out.println("Dibujando cuadrado");
}
public void dibujarCirculo() {
System.out.println("Dibujando circulo");
}
public void dibujarRectangulo() {
System.out.println("Dibujando rectangulo");
}
/*Este metodo tiene una implementacin vaca*/
public void dibujarFiguraHumana() {
}
}

Vemos claramente que la clase implementa los cuatro mtodos de la interfaz,


pero el mtodo dibujarFiguraHumana tiene una implementacin vaca.
Repetimos nuevamente: una clase debe implementar todos los mtodos de
la interfaz, y si se desea esa implementacin puede estar vaca.

Ahora nos podemos preguntar, qu es una interfaz?

Las interfaces
Una interfaz es una agrupacin de mtodos declarados ms no
implementados, que sirven para definir un conjunto de funcionalidades que
una clase debe implementar. Tambin debemos saber que los mtodos en

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos

las interfaces siempre deben de tener una visibilidad del tipo public.
Recordar que una interfaz slo define el qu se hace, mas no el cmo se
hace.

Implementando mltiples interfaces a la vez


En Java es posible que una clase implemente ms de una interfaz a la vez. Por
ejemplo, imaginemos que tenemos el siguiente diagrama que representa a
personas que son expertas en natacin y artes marciales:

En este caso tenemos que implementar en la clase Persona la interfaz


ExpertoEnNatacion y la interfaz ExpertoEnArtesMarciales. En Java la
implementacin la realizamos de la siguiente manera:

Interfaz ExpertoEnNatacion.java
public interface ExpertoEnNatacion {
public void nadarEstiloLibre();

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos


public void nadarEstiloEspalda();
public void nadarEstiloBuceo();
public void nadarEstiloMariposa();
}

Interfaz ExpertoEnArtesMarciales.java
public interface ExpertoEnArtesMarciales {
public void darGolpeDePatada();
public void darGolpeDeMano();
public void darSaltoConPatada();
}

Clase Persona.java
public class Persona implements ExpertoEnNatacion, ExpertoEnArtesMarciales{
public void caminar(){
System.out.println("Caminando");
}
public void comer(){
System.out.println("Comiendo");
}
public void dormir(){
System.out.println("Durmiendo");
}
public void nadarEstiloLibre() {
System.out.println("Nadando estilo libre");
}
public void nadarEstiloEspalda() {
System.out.println("Nadando estilo espalda");
}
public void nadarEstiloBuceo() {
System.out.println("Nadando estilo buceo");
}
public void nadarEstiloMariposa() {
System.out.println("Nadando estilo mariposa");
}
public void darGolpeDePatada() {
System.out.println("Dando golpe de patada");
}
public void darGolpeDeMano() {

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos


System.out.println("Dando golpe de mano");
}
public void darSaltoConPatada() {
System.out.println("Dando salto con patada");
}
}

Como vemos en este ejemplo es muy fcil implementar ms de una interfaz a


la vez, slo tenemos que separar la declaracin de qu interfaces vamos a
implementar por medio de comas.

Verificando la instancia que implementa la interfaz


Para entender esto usaremos las clases y la interfaz que definimos en el
ejemplo de las calculadoras. Creemos una clase llamada Programa:

Clase Programa.java
public class Programa {
public static void main(String[] args){
/*Definimos una variable del tipo de la interfaz*/
Calculadora calculadora = null;
/*Instanciamos la interfaz con alguna de las clases que la
implementa*/
calculadora = new CalculadoraComun();
//calculadora = new CalculadoraCientifica();
/*Verificamos a qu instancia pertenece*/
if(calculadora instanceof CalculadoraComun){
System.out.println("La calculadora se cre como una comn");
}else{
if(calculadora instanceof CalculadoraCientifica){
System.out.println("La calculadora se cre como una
cientfica");
}
}
/*Llamamos a un mtodo*/
System.out.println(calculadora.sumar(1, 2));
}

Prof. Alonso Ral Melgarejo Galvn

UNMSM Anlisis y Diseo de Algoritmos


}

De forma similar a la herencia, podemos declarar una variable del tipo de la


interfaz e instanciarla con un constructor de alguna de las clases que la
implemente. Tambin, para saber qu clase implement la variable de la
interfaz que usamos, utilizamos la palabra reservada instanceof

Emulando la herencia mltiple en Java


Ahora que conocemos las interfaces, podemos mostrar las dos formas en que
es posible emular la herencia mltiple.

La primera de ellas hace uso del concepto de jerarqua de herencia en la


cual una clase A hereda de una clase B, y esta a su vez hereda de la clase
C. De esta manera por transitividad la clase A hereda de C, con esto
logramos que A herede tanto de B como de C.

La otra forma de emular la herencia mltiple es usando las interfaces. Aqu


creamos tantas interfaces como necesitemos y definimos los mtodos en
ellas, luego hacemos que una clase las implemente. De esta forma simulamos
una herencia mltiple de mtodos sin implementacin.

Debemos recordar, estas son formas de emular la herencia mltiple en Java,


pero realmente no es herencia mltiple ya que no cumple con todas las
pautas necesarias para definirla como tal.

Prof. Alonso Ral Melgarejo Galvn

Vous aimerez peut-être aussi