El objetivo es la reutilización del software POO en Java IV ... Ejemplo (2/2) Determinar si en las...
Transcript of El objetivo es la reutilización del software POO en Java IV ... Ejemplo (2/2) Determinar si en las...
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
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
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
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
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
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
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
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.
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; } }
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.
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
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
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
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� );
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… }
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
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” );
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; } }
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
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
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.