Java POO 4 Herencia

21
POO en Java IV: Herencia (Parte 1) Franco Guidi Polanco Escuela de Ingeniería Industrial Pontificia Universidad Católica de Valparaíso, Chile [email protected] Actualización: 22 de Agosto de 2011 2 Franco Guidi Polanco Herencia Es la derivación de una clase a partir de otra existente. El objetivo es la reutilización del software desarrollado. Herencia 3 Franco Guidi Polanco Súperclases y subclases La clase de la cual se deriva otra clase se denomina clase base, súperclase o clase padre. Una clase derivada de una súperclase recibe también el nombre de subclase o clase hija. La herencia aplica en relaciones de naturaleza B es un tipo de A Vehículo Camión Súperclase Clase base Clase padre Subclase Clase derivada Clase hija 4 Súperclases y subclases La subclases heredan propiedades de su súperclase. Una subclase, respecto de su súperclase: Agrega nuevas propiedades Modifica propiedades heredadas. Vehículo Camión Patente Marca ----- Avanza Patente Marca Carga máxima ----- Avanza Activa tolva Franco Guidi Polanco

Transcript of Java POO 4 Herencia

Page 1: Java POO 4 Herencia

POO en Java IV: Herencia (Parte 1)

Franco Guidi Polanco Escuela de Ingeniería Industrial

Pontificia Universidad Católica de Valparaíso, Chile [email protected]

Actualización: 22 de Agosto de 2011

2 Franco Guidi Polanco

Herencia

 Es la derivación de una clase a partir de otra existente.

 El objetivo es la reutilización del software desarrollado.

Herencia

3 Franco Guidi Polanco

Súperclases y subclases

 La clase de la cual se deriva otra clase se denomina clase base, súperclase o clase padre.

 Una clase derivada de una súperclase recibe también el nombre de subclase o clase hija.

 La herencia aplica en relaciones de naturaleza �B es un tipo de A�

Vehículo

Camión

Súperclase Clase base Clase padre

Subclase Clase derivada Clase hija

4

Súperclases y subclases

 La subclases heredan propiedades de su súperclase.  Una subclase, respecto de su súperclase:

  Agrega nuevas propiedades   Modifica propiedades heredadas.

Vehículo

Camión

Patente Marca ----- Avanza

Patente Marca Carga máxima ----- Avanza Activa tolva

Franco Guidi Polanco

Page 2: Java POO 4 Herencia

5 Franco Guidi Polanco

Herencia simple

 Una clase es subclase de una única súperclase.

Vehículo

Camión

6 Franco Guidi Polanco

Herencia múltiple

 Una clase es subclase de más de una súperclase.

 Java no soporta la herencia múltiple.

Vehículos terrestres

Vehículos anfibios

Vehículos acuáticos

7 Franco Guidi Polanco

Jerarquías de Herencia

 La herencia organiza clases bases y derivadas en jerarquías de clases.

Persona

Alumno Profesor

Profesor hora

Alumno pregrado

Alumno magíster

 Rut, nombre  set y get nombre

+ Especialidad + set y get Especialidad

+ Horas + set y get Horas

+ Universidad + set y get Universidad

+ Carrera + set y get Carrera

+ Tesis + set y get Tesis

8

Ejemplo (1/2)

 Determinar si en las siguientes situaciones existe una relación de herencia entre las clases (indicadas en negrita):

Caso 1 Caso 2 Caso 3 Todo

Electrodoméstico se enciende y apaga. El Horno microondas

además abre y cierra su puerta.

Los Bienes raíces tienen un Rol de

identificación. Una Casa tiene también un

Jefe de hogar y un Negocio tiene una Patente comercial

Un Camión tiene Patente. Un Conductor

tiene un camión conducido.

Electrodoméstico

Horno Microondas

Bien Raíz

Casa Negocio X Franco Guidi Polanco

Page 3: Java POO 4 Herencia

9

Ejemplo (2/2)

 Determinar si en las siguientes situaciones existe una relación de herencia entre las clases (indicadas en negrita):

Caso 4 Caso 5 Caso 6 Los Archivos

Multimediales pueden ser Imágenes o

Música. Las imágenes pueden ser a Color o

Blanco y Negro.

Un Avión tiene Fuselaje, Alas y

Motores.

Una Gaviota vuela. Una Abeja vuela y

además tiene aguijón.

X X Multimedia

Música Imagen

Color B/N

Franco Guidi Polanco 10 Franco Guidi Polanco

Implementación de jerarquías de herencia

 Para crear una subclase a partir de una superclase, en Java la subclase debe declararse:

public class NombreSubclase extends NombreSuperclase

 Ejemplo:

Persona

Alumno

public class Alumno extends Persona

11 Franco Guidi Polanco

Implementación de jerarquías de herencia: ejemplo

 NOTA: Supondremos, por el momento, todos los miembros públicos.

Persona

Alumno

Atributos: - RUT - Nombre

Operaciones: -set y get RUT - set y get Nombre

Atributos: - RUT - Nombre - Rol UCV

Operaciones: -set y get RUT - set y get Nombre - set y get Rol UCV

 Implementar las clases Persona y Alumno, de acuerdo con lo siguiente:

12 Franco Guidi Polanco

Implementación de jerarquías de herencia

public class Persona { public String rut; public String nombre; public Persona() { rut = "00000000-0"; nombre = ""; } public void setRut(String r){ rut = r; } public String getRut(){ return rut; } public void setNombre(String n){ nombre = n; } public String getNombre(){ return nombre; } }

public class Alumno extends Persona { public String rolUCV; public Alumno() { rolUCV = �000000-0"; } public void setRolUCV(String r){ rolUCV = r; } public String getRolUCV(){ return rolUCV; } public String quiénSoy(){

return rut + nombre + rolUCV; } }

Súperclase Subclase

Page 4: Java POO 4 Herencia

13 Franco Guidi Polanco

Miembros heredados (verdad parcial)

 Una subclase hereda de su súperclase (por el momento):   Variables de instancia públicas   Métodos públicos

 Todos los anteriores pueden ser utilizados en la subclase �como si hubieran sido declarados en ella�.

POO en Java IV: Herencia (Parte 2)

Franco Guidi Polanco Escuela de Ingeniería Industrial

Pontificia Universidad Católica de Valparaíso, Chile [email protected]

Actualización: 22 de Agosto de 2011

15

Presentación

 Hemos visto:   La definición de herencia (y la relación subyacente entre

“tipos”)   El concepto de súperclase y subclase   La definición de jerarquía de herencia   La declaración de una subclase en Java   La extensión de clases que poseen miembros públicos.

 Veremos:   Un problema de diseño e implementación con herencia,

utilizando miembros públicos.   Se desarrollará una extensión del sistema desarrollado

en el problema.

Franco Guidi Polanco 16

Ejercicio

Implemente las clases Vehículo, Autobús y Camión, dados los siguientes antecedentes:  Todo Vehículo tiene patente y marca.  Los Autobuses y los Camiones son Vehículos.  Todo Autobús tiene cantidad de asientos.  Todo Camión tiene carga en toneladas.

Franco Guidi Polanco

Page 5: Java POO 4 Herencia

17

Análisis

 Jerarquía de clases

Vehículo  Patente, marca

Autobús  Asientos Camión  Carga

Franco Guidi Polanco 18

Implementación

 Vehículo: public class Vehiculo{

public String patente; public String marca; public void setPatente(String p){ patente = p; } public String setMarca(String m){ marca = m; } public String getPatente(){ return patente; } public String getMarca(){ return marca; }

} Franco Guidi Polanco

19

Implementación

 Autobús

public class Autobus extends Vehiculo{ public int asientos; public void setAsientos(int a){ asientos = a; } public int getAsientos(){ return asientos; }

}

Franco Guidi Polanco 20

Implementación

 Camión:

public class Camion extends Vehiculo{ public int carga; public void setCarga(int c){ carga = c; } public int getCarga(){ return carga; }

}

Franco Guidi Polanco

Page 6: Java POO 4 Herencia

21

Uso de las clases desarrolladas

 Entonces una aplicación podría realizar lo siguiente:

public class Ejemplo { public static void main( String arg[]){

… Autobus bus1 = new Autobus(); bus1.setPatente( “AX1313” ); bus1.setMarca( “Mercedes” ); bus1.setAsientos( 40 ); … Camion cam1 = new Camion(); cam1.setPatente( “BX1515” ); cam1.setMarca( “Iveco” ); cam1.setCarga( 2000 ); …

} }

Métodos heredados de Vehículo

Métodos heredados de Vehículo

Franco Guidi Polanco 22

Una extensión al problema

 Suponga que se desea agregar al sistema un Camión con compartimientos, el cual posee patente, marca, carga máxima y una cantidad de compartimientos. Este camión es capaz de calcular la capacidad de carga por compartimiento (equivalente a la carga total, dividida por la cantidad de compartimientos). Además provee un método que retorna un String de descripción, compuesto por Marca + Cantidad de compartimientos

¿Qué se debe hacer? Franco Guidi Polanco

23

Análisis

 El Camión con compartimientos es una subclase de Camión.

Vehículo

Autobús Camión

 Patente, marca

 Asientos  Carga

Camión con compartimientos

 Compartimientos

Franco Guidi Polanco 24

Implementación

 Camión con compartimientos: public class CamionCompartimientos extends Camion{

public int compartimientos=1; public void setCompartimientos(int c){ compartimientos = c; } public int getCompartimientos(){ return compartimientos; } public int getCargaCompartimiento(){ return carga/compartimientos; } public String getDescripción(){ return marca + compartimientos; }

}

carga: es heredado (desde Camión)

marca: es heredado (desde Vehículo)

Franco Guidi Polanco

Page 7: Java POO 4 Herencia

25

Uso de la nueva clase

public class Ejemplo2 { public static void main( String arg[]){ … CamionCompartimientos cam2 = new CamionCompartimientos(); cam2.setPatente( “CX1818” ); cam2.setMarca( “Ford” ); cam2.setCarga( 2500 ); cam2.setCompartimientos( 5 ); System.out.println( cam2.getCargaCompartimiento() ); System.out.println( cam2.getdescripción() ); …

} }

Métodos heredados de Vehículo Método heredado de Camión

Franco Guidi Polanco

POO en Java IV: Herencia (Parte 3)

Franco Guidi Polanco Escuela de Ingeniería Industrial

Pontificia Universidad Católica de Valparaíso, Chile [email protected]

Actualización: 22 de Agosto de 2011

27

Presentación

 Hemos visto:   Los conceptos funamentales asociados a la herencia.   La implementación de subclases en Java, en presencia

de miembros públicos en la súperclase.

 Veremos:   La implementación de subclases en Java, cuando la

súperclase posee variables de instancia privadas.   La relación entre constructores de súperclases y

subclases.   La relación de las clases con la clase Object.

Franco Guidi Polanco 28 Franco Guidi Polanco 28

Repaso: extensión de una clase con miembros públicos

public class Persona { public String rut; public String nombre; public Persona() { rut = "00000000-0"; nombre = ""; } public void setRut(String r){ rut = r; } public String getRut(){ return rut; } public void setNombre(String n){ nombre = n; } public String getNombre(){ return nombre; } }

public class Alumno extends Persona { public String rolUCV; public Alumno() { rolUCV = �000000-0"; } public void setRolUCV(String r){ rolUCV = r; } public String getRolUCV(){ return rolUCV; } public String quiénSoy(){

return rut + nombre + rolUCV; } }

Súperclase Subclase

Page 8: Java POO 4 Herencia

29 Franco Guidi Polanco 29

Miembros heredados (verdad parcial)

 Una subclase hereda de su súperclase (por el momento):   Variables de instancia públicas   Métodos públicos

 Todos los anteriores pueden ser utilizados en la subclase �como si hubieran sido declarados en ella�.

30 Franco Guidi Polanco 30

Miembros no heredados

 Una subclase no hereda:   Propiedades privadas   Constructores

 Los miembros no heredados no pueden aparecer en el código de la subclase.

31 Franco Guidi Polanco 31

Miembros no heredados: variables de instancia privadas

 No funciona:

public class Persona { private String rut; private String nombre; public Persona() { rut = "00000000-0"; nombre = ""; } public void setRut(String r){ rut = r; } public String getRut(){ return rut; } public void setNombre(String n){ nombre = n; } public String getNombre(){ return nombre; } }

public class Alumno extends Persona { private String rolUCV; public Alumno() { rolUCV = �000000-0"; } public void setRolUCV(String r){ rolUCV = r; } public String getRolUCV(){ return rolUCV; } public String quiénSoy(){

return rut + nombre + rolUCV; } }

Error: no pueden ser accesadas directamente (No compila)

32 Franco Guidi Polanco 32

Miembros no heredados: variables de instancia privadas

 Las variables privadas no son heredadas, por lo que no pueden aparecer en el código de la subclase.

 Sin embargo se puede hacer uso indirecto de ellas en la subclase, a través de los métodos públicos de manipulación implementados en la respectiva súperclase.

Page 9: Java POO 4 Herencia

33 Franco Guidi Polanco 33

Miembros no heredados: variables de instancia privadas

 Ejemplo correcto: public class Persona { private String rut; private String nombre; public Persona() { rut = "00000000-0"; nombre = ""; } public void setRut(String r){ rut = r; } public String getRut(){ return rut; } public void setNombre(String n){ nombre = n; } public String getNombre(){ return nombre; } }

public class Alumno extends Persona { private String rolUCV; public Alumno() { rolUCV = �000000-0"; } public void setRolUCV(String r){ rolUCV = r; } public String getRolUCV(){ return rolUCV; } public String quiénSoy(){

return getRut() + getNombre() + rolUCV; } }

Esto sí funciona 34 Franco Guidi Polanco 34

Miembros no heredados: constructores

 Los constructores no son heredados, por lo que cada subclase debe tener su(s) propio(s) constructor(es).

 Sin embargo en los constructores se puede invocar al constructor de la superclase con la instrucción:

super( lista parámetros )

 La instrucción super debe ser la primera instrucción del constructor.

35 Franco Guidi Polanco 35

Uso de super en constructores

 Ejemplo 1:

public class Persona { private String rut; private String nombre; public Persona(String r, String n) { rut = r; nombre = n; } public void setRut(String r){ rut = r; } public String getRut(){ return rut; } public void setNombre(String n){ nombre = n; } public String getNombre(){ return nombre; } }

public class Alumno extends Persona { private String rolUCV; public Alumno() { super( �000000-0�, �N/A� ); rolUCV = �000000-0"; } public void setRolUCV(String r){ rolUCV = r; } public String getRolUCV(){ return rolUCV; } public String quiénSoy(){ return getRut() + getNombre() + rolUCV; } }

36 Franco Guidi Polanco 36

Uso de super en constructores

 Ejemplo 2:

public class Persona { private String rut; private String nombre; public Persona(String r, String n) { rut = r; nombre = n; } public void setRut(String r){ rut = r; } public String getRut(){ return rut; } public void setNombre(String n){ nombre = n; } public String getNombre(){ return nombre; } }

public class Alumno extends Persona { private String rolUCV; public Alumno(String r, String n, String l) { super( r, n ); rolUCV = l; } public void setRolUCV(String r){ rolUCV = r; } public String getRolUCV(){ return rolUCV; } public String quiénSoy(){ return getRut() + getNombre() + rolUCV; } }

Page 10: Java POO 4 Herencia

37 Franco Guidi Polanco 37

Herencia y constructores: la verdad parcial

 Todo subclase debe incluir una referencia super a algún constructor de la superclase.

 Si no se incluye la referencia super, Java incluye automáticamente una referencia al constructor sin parámetros de la superclase. Es decir incluye:

super()

 Notar que se produce un error cuando no existe un constructor sin parámetros en la superclase y se omite la referencia super en la subclase ¿por qué?

38 Franco Guidi Polanco 38

Herencia y constructores

 Dos clases equivalentes:

public class Alumno extends Persona {

private String rolUCV; public Alumno() { rolUCV = �000000-0"; } public void setRolUCV(String r){ rolUCV = r; } public String getRolUCV(){ return rolUCV; } public String quiénSoy(){ return getRut() + getNombre() + rolUCV; } }

public class Alumno extends Persona {

private String rolUCV; public Alumno() { super(); rolUCV = �000000-0"; } public void setRolUCV(String r){ rolUCV = r; } public String getRolUCV(){ return rolUCV; } public String quiénSoy(){ return getRut() + getNombre() + rolUCV; } }

39 Franco Guidi Polanco 39

Herencia y constructores: ¡Atención!

 ¿Qué pasa en el siguiente caso?

public class Persona { private String rut; private String nombre; public Persona(String r, String n) { rut = r; nombre = n; } public void setRut(String r){ rut = r; } public String getRut(){ return rut; } public void setNombre(String n){ nombre = n; } public String getNombre(){ return nombre; } }

public class Alumno extends Persona {

private String rolUCV; public Alumno() {

rolUCV = �000000-0"; } public void setRolUCV(String r){ rolUCV = r; } public String getRolUCV(){ return rolUCV; } public String quiénSoy(){ return getRut() + getNombre() + rolUCV; } }

public Alumno() { super(); rolUCV = �000000-0"; }

Java incluye automáticamente una referencia super(), pero a un constructor inexistente en la súperclase.

No compila

40 Franco Guidi Polanco 40

Herencia y constructores: la verdad total

 En Java toda clase extiende otra clase.  Las clases que no declaran extender a otras,

extienden a la clase Object (del package java.lang).

 Object es la superclase (directa o indirecta) de todas las clases.

 Todas las clases son subclases de Object o de otra subclase.

Por lo tanto: todos los constructores incluyen (explícitamente o no) una referencia al constructor de su superclase.

Page 11: Java POO 4 Herencia

41

Herencia y constructores: la verdad total

Persona

Alumno Profesor

Profesor hora

Alumno pregrado

Alumno magíster

Object

Bien Raíz

Casa Negocio

Vehículo

Camión

Franco Guidi Polanco

POO en Java IV: Herencia (Parte 4)

Franco Guidi Polanco Escuela de Ingeniería Industrial

Pontificia Universidad Católica de Valparaíso, Chile [email protected]

Actualización: 22 de Agosto de 2011

Presentación

 Hemos visto:   Implementación de jerarquías de herencia con variables

de instancia públicas y privadas.   Invocación de constructores de súperclases mediante super.

  La clase Object como la súperclase de toda jerarquía de herencia en Java.

 Veremos:   Un ejercicio de desarrollo de una jerarquía de herencia

con variables de instancia privadas, y con referencias explícitas a constructor de la súperclase.

  La representación de clases y jerarquías de herencia mediante diagramas de clases de UML.

Franco Guidi Polanco 43 44

Ejercicio: Implementar las siguientes clases

  Un videojuego tiene Personajes. Cada personaje tiene un nombre (String) y un nivel propio de energía (int). Además implementan el método alimentarse, que recibe por parámetro una cantidad de energía (int) con el que incrementa el nivel propio de energía. Los personajes pueden ser:   Guerreros: tienen además un arma (String). Al momento de la

instanciación reciben su nombre, arma y nivel propio de energía inicial. Los guerreros tienen un método combatir que recibe por parámetro la cantidad de energía a gastar en el ataque, la cual es descontada de su nivel propio de energía. El método combatir retorna el arma y la cantidad de energía del ataque concatenados.

  Magos: tienen además un poder (String). Al momento de la instanciación reciben su nombre y poder. Los magos son siempre creados con un nivel propio de energía igual a 100. Proveen un método encantar, que disminuye en 2 unidades el nivel propio de energía y que retorna el poder del mago.

Franco Guidi Polanco

Page 12: Java POO 4 Herencia

Análisis y diseño

 La clase Personaje:

Franco Guidi Polanco 45

Personaje

- nombre: String - energía: int

+getNombre(): String +getEnergia(): int +alimentarse(energiaNueva:int) +consumirEnergia(gastoEnergia:int) +Personaje(nombre:String, energia:int)

Nombre de la clase!

Variables de instancia!

Métodos y constructores!

Visibilidad privada (-)!

Visibilidad pública (+)!

Los constructores van subrayados!

Análisis y diseño

Franco Guidi Polanco 46

Personaje

Guerrero

- nombre: String - energía: int

+getNombre(): String +getEnergia(): int +alimentarse(energiaNueva:int) +consumirEnergia(gastoEnergia:int) +Personaje(nombre:String, energia:int)

-arma: String

+combatir(energ:int):String +Guerrero(nombre:String, energía:int, arma:String)

Mago

-poder: String

+encantar():String +Mago(nombre:String, poder:String)

Implementación

 Clase Personaje:

Franco Guidi Polanco 47

public class Personaje{

private String nombre; private int energia;

public Personaje(String nombre, int energia){ this.nombre = nombre; this.energia = energia; }

public String getNombre(){ return nombre; }

public int getEnergia(){ return energia; }

public void alimentarse(int energiaNueva){ energia = energia + energiaNueva; }

public void consumirEnergia(int gastoEnerg){ energia = energia - gastoEnerg; }

}

Personaje

- nombre: String - energía: int

+getNombre(): String +getEnergia(): int +alimentarse(energiaNueva:int) +consumirEnergia(gastoEnergia:int) +Personaje(nombre:String, energia:int)

Implementación

 Clase Guerrero:

Franco Guidi Polanco 48

public class Guerrero extends Personaje{

private String arma; public Guerrero(String nombre, int energia, String arma){

super(nombre, energia); this.arma = arma;

} public String combatir(int energ){

actualizaEnergia( -1*energ ); return arma + energ;

}

}

Guerrero

-arma: String

+combatir(energ:int):String +Guerrero(nombre:String, energía:int, arma:String)

Personaje

Page 13: Java POO 4 Herencia

Implementación

 Clase Mago:

Franco Guidi Polanco 49

public class Mago extends Personaje{

private String poder; public Mago(String nombre, String poder){

super(nombre, 100); this.poder = poder;

} public String encantar(){

actualizaEnergia( -2 ); return poder;

}

}

Personaje

Mago

-poder: String

+encantar(energ:int):String +Mago(nombre:String, poder:String)

Uso de las clases

 Ejemplo:

Franco Guidi Polanco 50

… Guerrero g1 = new Guerrero(“Alfa”, 50, “Burbujitas de jabón”); g1.combatir( 2 ); System.out.println( “El nivel de energía de ” + g1.getNombre()

+ “ es ” + g1.getEnergia() ); … Mago m1 = new Mago( “Harry”, “Quemar” ); m1.encantar(); System.out.println( “El nivel de energía de ” + m1.getNombre()

+ “ es ” + m1.getEnergia() ); …

POO en Java IV: Herencia (Parte 5)

Franco Guidi Polanco Escuela de Ingeniería Industrial

Pontificia Universidad Católica de Valparaíso, Chile [email protected]

Actualización: 22 de Agosto de 2011

Presentación

 Hemos visto:   Implementación de jerarquías de herencia con variables de

instancia públicas y privadas e invocación de constructores de súperclases mediante super.

  La clase Object como la súperclase de toda jerarquía de herencia en Java.

  La notación del Diagrama de Clases de UML para clases y relaciones de herencia.

 Veremos:   Tratamiento de variables que referencian subtipos.   Sobreescritura de métodos.   Uso del operador instanceof para conocer el tipo de un objeto.   Casting en jerarquías de herencia.   Clases con miembros protegidos (protected).

Franco Guidi Polanco 52

Page 14: Java POO 4 Herencia

Referencias, tipos y subtipos

 Una variable de referencia puede referenciar objetos del mismo tipo de la variable (esto ya lo sabíamos). Ejemplo:

Persona p = new Persona();

 Una variable de referencia puede referenciar objetos de cualquier subtipo de la variable. Ejemplos:

Persona p = new Alumno(); Persona p = new Tesista();

Franco Guidi Polanco 53

Persona

Alumno

Tesista

Referencias, tipos y subtipos

 Dado que toda clase es subclase directa o indirecta de la clase Object, una variable de este tipo puede referenciar objetos de cualquier tipo. Ejemplos:

Object o = new Persona(); Object o = new Tesista(); Object o = new Lavadora();

 En consecuencia, un arreglo de tipo Object puede almacenar cualquier tipo de objeto en sus posiciones:

Object[] arr = new Object[10]; arr[1] = new Persona(); arr[2] = new Tesista(); arr[3] = new Lavadora();

Franco Guidi Polanco 54

Referencias, tipos y subtipos

 Una variable de referencia de un determinado tipo NO puede referenciar objetos de un súpertipo.

 Por lo anterior, las siguientes asignaciones NO son válidas: Alumno a = new Persona(); Tesista t = new Alumno(); Tesista t = new Persona();

Franco Guidi Polanco 55

Persona

Alumno

Tesista

56 Franco Guidi Polanco 56

Reconocimiento de clases: operador instanceof

 El operador instanceof permite reconocer la clase a la que pertenece un objeto referenciado desde una variable determinada.

 Formato: NombreVar instanceof NombreClase

 Ejemplo: if( pers instanceof Persona ) System.out.println( �La variable pers referencia a una Persona� ); else System.out.println( �La variable pers no referencia a una Persona� );

Page 15: Java POO 4 Herencia

57 Franco Guidi Polanco 57

Operador instanceof y herencia

 Todo objeto es instancia de la clase a la que pertenece, como también instancia de su superclase.

Electrodoméstico

Lavadora

Un objeto de la clase lavadora es también un electrodoméstico

58 Franco Guidi Polanco 58

Operador instanceof: ejemplo

 Suponer:

Persona

Profesor Alumno

Persona p1 =null: Profesor p2 = new Profesor(); Alumno p3 = new Alumno(); if( p1 instanceof Persona ) --> false! if( p2 instanceof Profesor ) --> true!if( p2 instanceof Persona ) --> true!if( p2 instanceof Alumno ) --> false! if( p3 instanceof Alumno ) --> true!if( p3 instanceof Persona ) --> true!if( p3 instanceof Profesor ) --> false!

Operador instanceof: ejemplo

Franco Guidi Polanco 59

Persona personas = new Persona[100]; // Supongamos que aquí se ingresan // al arreglo Personas, Alumnos // y Tesistas. … //Aquí se muestra la cantidad de tesistas cantidadTesistas = 0; for(int i=0; i< personas.length; i++)

if( personas[i] instanceof Tesista ) cantidadTesistas++;

System.out.println( “Hay” + cantidadTesistas + “ tesistas”); …

Persona

Alumno

Tesista

60 Franco Guidi Polanco 60

Sobreescritura de métodos

 Un método declarado e implementado en una súperclase puede ser reimplementado en una subclase. Esto se denomina sobreescritura de métodos.

 Conceptualmente significa que la subclase realiza la misma operación de la súper clase, pero de un modo distinto.

 Esto es un caso de polimorfismo. public class Persona { private String rut; private String nombre; public String getRut(){ return rut; } public String getNombre(){ return nombre; } public String identificarse(){ return rut + nombre; } //otros miembros de la clase… }

public class Alumno extends Persona {

private String carrera; public String identificarse(){ return getRut() + getNombre() + carrera; }

//otros miembros de la clase… }

Page 16: Java POO 4 Herencia

61 Franco Guidi Polanco 61

Sobreescritura de métodos

 Consideremos estas clases en los siguientes ejemplos:

public class Persona { private String rut, nombre; public Persona(String r, String n){ rut = r; nombre = n; } public String getRut(){ return rut; } public String getNombre(){ return nombre; } public String identificarse(){ return rut + nombre; } }

public class Alumno extends Persona {

private String carrera; public Alumno(String r, String n, String c){ super(r,n); carrera = c; } public String identificarse(){ return getRut() + getNombre() + carrera; } }

62

¿Qué ocurre en las siguientes situaciones?

Persona a = new Persona(�100�, �Matías�); System.out.println( a.identificarse() );

Alumno b = new Alumno(�100�, �Matías�, �Ind�); System.out.println( b.identificarse() );

100Matías

100MatíasInd

a

getRut()

getNombre()

identificarse()

100 Matías

b

public String identificarse(){ return rut + nombre; }

Franco Guidi Polanco

getRut()

getNombre()

identificarse()

100 Matías Ind public String identificarse(){ return getRut() + getNombre() + carrera; }

¿Qué ocurre en la siguiente situación?

Franco Guidi Polanco 63

Persona a = new Alumno( �100�, �Matías�, �Ind�); System.out.println( a.identificarse() );

a

getRut()

getNombre()

identificarse()

100 Matías Ind public String identificarse(){ return getRut() + getNombre() + carrera; }

100MatíasInd

Java resuelve en tiempo de ejecución la asociación entre la variable de referencia y el método que debe invocar, en función del objeto que se encuentre referenciado en ella.

64 Franco Guidi Polanco 64

Sobreescritura de métodos

public class Persona { private String rut, nombre; public Persona(String r, String n){ rut = r; nombre = n; } public String getRut(){ return rut;} public String getNombre(){ return nombre;} public String identificarse(){ return rut + nombre; } }

public class Alumno extends Persona {

private String carrera; public Alumno(String r, String n, String c){ super(r,n); carrera = c; } public String identificarse(){ return getRut() + getNombre() + carrera; } }

Persona a = new Alumno( �100�, �Matías�, �Ind�); System.out.println( a.identificarse() );

public String identificarse(){ return getRut() + getNombre() + carrera; }

100MatíasInd

Page 17: Java POO 4 Herencia

65 Franco Guidi Polanco 65

Sobreescritura de métodos

 El compilador Java es responsable de verificar que el método pertenezca al tipo de dato declarado por la variable.

 El intérprete Java es responsable de identificar y ejecutar la implementación del método correspondiente al tipo de objeto referenciado en el momento por la variable.

Persona a = new Alumno( �100�, �Matías�, �Ind�); System.out.println( a.identificarse() );

66 Franco Guidi Polanco 66

Herencia y acceso a miembros de una clase

Persona a = new Persona(); a.setDatos( “1000-2”, “Luis”); Alumno b = new Alumno(); b.setDatos( “2000-3”, “Pamela” ); b.matricularse( “Industrial” );

  Esto debe funcionar:

public class Persona { private String rut; private String nombre; public setDatos(String r, String n) { rut = r; nombre = n; } public String getRut(){ return rut; } public String getNombre(){ return nombre; } }

public class Alumno extends Persona { private String carrera; public String matricularse( String c){ carrera = c; } }

67 Franco Guidi Polanco 67

Herencia y acceso a miembros de una clase

  ¿Esto funciona?

public class Persona { private String rut; private String nombre; public setDatos(String r, String n) { rut = r; nombre = n; } public String getRut(){ return rut; } public String getNombre(){ return nombre; } }

public class Alumno extends Persona { private String carrera; public String matricularse( String c){ carrera = c; } }

Persona c = new Alumno(); c.setDatos( “1000-2”, “Luis”); c.matricularse( “Comercial” );

Error: el compilador determina que este método no pertenece a Persona. Sin embargo la variable contiene referencia a un Alumno, que es un tipo de Persona (y que posee este método).

68 Franco Guidi Polanco 68

Casting

 Es necesario introducir un casting para indicar al compilador que el objeto referenciado en la variable es efectivamente una instancia de Alumno:

public class Persona { private String rut; private String nombre; public setDatos(String r, String n) { rut = r; nombre = n; } public String getRut(){ return rut; } public String getNombre(){ return nombre; } }

public class Alumno extends Persona { private String carrera; public String matricularse( String c){ carrera = c; } }

Persona c = new Alumno(); c.setDatos( “1000-2”, “Luis”); ( (Alumno)c ).matricularse( “Industrial” );

Page 18: Java POO 4 Herencia

69 Franco Guidi Polanco 69

Casting

 El casting no convierte objetos, simplemente explicita el tipo de objeto referenciado en una variable.

Persona

Profesor Alumno

Persona a = new Profesor(); Profesor b = (Profesor) a; // OK Alumno c = (Alumno) a; // ERROR

Persona a = new Persona(); Profesor b = (Profesor) a; // ERROR Alumno c = (Alumno) a; // ERROR

Alumno a = new Alumno(); Profesor b = (Profesor) a; // ERROR

Persona a = new Profesor(); Profesor b = a; // ERROR

70 Franco Guidi Polanco 70

Miembros protegidos de una clase

 El modificador de visibilidad protected, permite declarar visibilidad “protegida” en variables de instancia y métodos.

 Los miembros de una clase con visibilidad protegida son sólo accesibles desde la misma clase o desde cualquier subclase de ella (no son accesibles desde otras clases).

71 Franco Guidi Polanco 71

Miembros protegidos de una clase

 Por lo tanto, una subclase hereda de su superclase:   Variables de instancia protegidas y públicas   Métodos protegidos y públicos

72 Franco Guidi Polanco 72

Miembros protegidos de una clase

 Ejemplo: public class Persona { protected String rut; protected String nombre; public Persona(String r, String n) { rut = r; nombre = n; } public void setRut(String r){ rut = r; } public String getRut(){ return rut; } public void setNombre(String n){ nombre = n; } public String getNombre(){ return nombre; } }

public class Alumno extends Persona {

private String rolUCV; public Alumno() { super( �000000-0�, �N/A� ); rolUCV = �000000-0"; } public String quiénSoy(){ return rut + nombre + rolUCV; } }

Page 19: Java POO 4 Herencia

POO en Java IV: Herencia (Parte 6)

Franco Guidi Polanco Escuela de Ingeniería Industrial

Pontificia Universidad Católica de Valparaíso, Chile [email protected]

Actualización: 22 de Agosto de 2011

74

Identificación de superclases

  Contexto: se está desarrollando una aplicación que trabaja con CD’s, DVD’s y discos de vinilo.

  Problema: se establece que a pesar de tener sus propios atributos, todos ellos disponen de código, sello discográfico y autor. Se desea evitar duplicidad de código.

  Decisión: se determina la conveniencia de crear la clase “ProductoMusical”, que agrupa las propiedades comunes de los tres tipos de productos.

Franco Guidi Polanco 74

ProductoMusical

Vinilo DVD CD

código sello autor

La superclase aparece por factorización de propiedades comunes

75

Clases abstractas

  En el ejemplo anterior la clase ProductoMusical es abstracta (no representa entidades presentes en el dominio).

  Esta condición se explicita en el diseño, declarando la clase como abstracta.

  Una clase abstracta no puede ser instanciada, ha sido diseñada sólo para ser extendida.

Franco Guidi Polanco 75

ProductoMusical {abstract}

Vinilo DVD CD

código sello autor

public abstract class ProductoMusical { private int código; private String sello; ... }

76

Clases abstractas

 Otro ejemplo: un software trabaja con distintas figuras geométricas, todas ellas polígonos, con algunas propiedades en común (ej. cantidad de lados).

Franco Guidi Polanco 76

Polígono

Page 20: Java POO 4 Herencia

77

Clases abstractas

Franco Guidi Polanco 77

public abstract class Poligono { protected int lados; public void setLados(int l){ lados = l; } ...

}

public class Cuadrado extends Poligono { private int longitud; public void setLongitud(double l) { longitud = l; } ...

}

Polígono

78

Métodos abstractos

 Supongamos que en el ejemplo anterior todos los polígonos deben proveer un método de cálculo de área.

 Conflicto de “fuerzas” en diseño:   Todos los polígonos deben proveer el

método, por lo tanto debiese “aparecer” a nivel de la superclase Polígono.

  La operación del método depende de cada polígono concreto (ej. área de cuagrado: lado2, área de triángulo base * altura /2, etc.), por lo tanto no puede establecerse una lógica común a nivel de superclase.

 Solución: declarar método como abstracto en la superclase.

Franco Guidi Polanco 78

Polígono

79

Métodos abstractos

 Un método abstracto es un método que se declara en una superclase, pero sin proveer implementación.

 La implementación de un método abstracto se difiere para sus subclases.

 Una clase que declara uno o más métodos abstractos es necesariamente abstracta (y debe ser declarada como tal).

 Si una subclase no provee implementación para un método abstracto que hereda de su superclase, es necesariamente abstracta (y debe ser declarada como tal).

Franco Guidi Polanco 79 80

Métodos abstractos

Franco Guidi Polanco

80

public abstract class Poligono { protected int lados; public int setLados(int l){ lados = l; } public abstract double getArea(); ...

}

public class Cuadrado extends Poligono { private double longitud; public void setLongitud(double l) { longitud = l; }

public double getArea(){ return longitud*longitud; } ...

}

Polígono

Page 21: Java POO 4 Herencia

81

Consecuencias del uso de métodos abstractos

 Si una superclase declara algún método abstracto, entonces:   Las subclases concretas deben implementarlo.   Las variables de referencia declaradas del tipo

de la superclase pueden recibir invocaciones al método abstracto, sin necesidad de casting. Ejemplo:

Franco Guidi Polanco 81

Polígono figura = new Triángulo(); double sup = figura.getArea();

getArea() fue declarado como método abstracto en Polígono.