1. Herencia
Es la derivación de una clase a partir de otra
existente.
El objetivo es la reutilización del software
POO en Java IV: Herencia desarrollado.
(Parte 1)
Franco Guidi Polanco
Escuela de Ingeniería Industrial
Pontificia Universidad Católica de Valparaíso, Chile Herencia
fguidi@ucv.cl
Actualización: 22 de Agosto de 2011
Franco Guidi Polanco 2
Súperclases y subclases Súperclases y subclases
La clase de la cual se deriva otra clase se denomina La subclases heredan propiedades de su súperclase.
clase base, súperclase o clase padre. Una subclase, respecto de su súperclase:
Agrega nuevas propiedades
Una clase derivada de una súperclase recibe también Modifica propiedades heredadas.
el nombre de subclase o clase hija.
Patente
Marca
Súperclase -----
Vehículo Clase base Avanza
Clase padre Vehículo
Subclase
Camión Clase derivada Patente
Clase hija Camión Marca
Carga máxima
-----
La herencia aplica en relaciones de naturaleza B es un Avanza
tipo de A Activa tolva
Franco Guidi Polanco 3 Franco Guidi Polanco 4
2. Herencia simple Herencia múltiple
Una clase es subclase de una única súperclase. Una clase es subclase de más de una súperclase.
Vehículos Vehículos
terrestres acuáticos
Vehículo
Vehículos
anfibios
Camión
Java no soporta la herencia múltiple.
Franco Guidi Polanco 5 Franco Guidi Polanco 6
Jerarquías de Herencia Ejemplo (1/2)
La herencia organiza clases bases y derivadas en Determinar si en las siguientes situaciones existe una
jerarquías de clases. relación de herencia entre las clases (indicadas en negrita):
Caso 1 Caso 2 Caso 3
Rut, nombre
Persona
set y get nombre Todo Los Bienes raíces Un Camión tiene
Electrodoméstico se tienen un Rol de Patente. Un Conductor
enciende y apaga. El identificación. Una tiene un camión
Horno microondas Casa tiene también un conducido.
+ Universidad Profesor + Especialidad además abre y cierra su Jefe de hogar y un
Alumno
+ set y get Universidad + set y get Especialidad puerta. Negocio tiene una
Patente comercial
+ Carrera
+ set y get Carrera
Franco Guidi Polanco
Alumno
pregrado
Alumno + Tesis
magíster + set y get Tesis
Profesor + Horas
hora + set y get Horas
7
Electrodoméstico
Horno Microondas
Franco Guidi Polanco
Casa
Bien Raíz
Negocio X 8
3. Ejemplo (2/2) Implementación de jerarquías de herencia
Determinar si en las siguientes situaciones existe una Para crear una subclase a partir de una superclase, en
relación de herencia entre las clases (indicadas en negrita): Java la subclase debe declararse:
Caso 4 Caso 5 Caso 6
Los Archivos Un Avión tiene Una Gaviota vuela.
Multimediales pueden Fuselaje, Alas y Una Abeja vuela y
public class NombreSubclase extends NombreSuperclase
ser Imágenes o Motores. además tiene aguijón.
Música. Las imágenes
pueden ser a Color o
Blanco y Negro. Ejemplo:
X X
Multimedia
Persona
public class Alumno extends Persona
Música Imagen
Color B/N Alumno
Franco Guidi Polanco 9 Franco Guidi Polanco 10
Implementación de jerarquías de herencia:
Implementación de jerarquías de herencia
ejemplo
Implementar las clases Persona y Alumno, de
acuerdo con lo siguiente: public class Persona { public class Alumno extends Persona {
public String rut; public String rolUCV;
Atributos: Operaciones: public String nombre;
Persona - RUT -set y get RUT
public Persona() {
public Alumno() {
rolUCV = 000000-0";
- Nombre - set y get Nombre rut = "00000000-0"; }
nombre = ""; } public void setRolUCV(String r){
public void setRut(String r){ rolUCV = r;
rut = r; } }
Atributos: Operaciones: public String getRut(){ public String getRolUCV(){
Alumno - RUT -set y get RUT return rut; }
public void setNombre(String n){ }
return rolUCV;
- Nombre - set y get Nombre nombre = n; } public String quiénSoy(){
- Rol UCV - set y get Rol UCV public String getNombre(){ return rut + nombre + rolUCV;
return nombre; } }
} }
NOTA: Supondremos, por el momento, todos los
miembros públicos. Súperclase Subclase
Franco Guidi Polanco 11 Franco Guidi Polanco 12
4. Miembros heredados (verdad parcial)
Una subclase hereda de su súperclase (por el
momento):
Variables de instancia públicas
Métodos públicos POO en Java IV: Herencia
(Parte 2)
Todos los anteriores pueden ser utilizados en la
subclase como si hubieran sido declarados en Franco Guidi Polanco
ella . Escuela de Ingeniería Industrial
Pontificia Universidad Católica de Valparaíso, Chile
fguidi@ucv.cl
Actualización: 22 de Agosto de 2011
Franco Guidi Polanco 13
Presentación Ejercicio
Hemos visto: Implemente las clases Vehículo, Autobús y
La definición de herencia (y la relación subyacente entre Camión, dados los siguientes antecedentes:
“tipos”) Todo Vehículo tiene patente y marca.
El concepto de súperclase y subclase
Los Autobuses y los Camiones son Vehículos.
La definición de jerarquía de herencia
Todo Autobús tiene cantidad de asientos.
La declaración de una subclase en Java
La extensión de clases que poseen miembros públicos. Todo Camión tiene carga en toneladas.
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 15 Franco Guidi Polanco 16
5. Análisis Implementación
Jerarquía de clases Vehículo:
public class Vehiculo{
public String patente;
Vehículo Patente, marca public String marca;
public void setPatente(String p){
patente = p;
}
public String setMarca(String m){
marca = m;
Asientos Autobús Camión Carga }
public String getPatente(){
return patente;
}
public String getMarca(){
return marca;
}
}
Franco Guidi Polanco 17 Franco Guidi Polanco 18
Implementación Implementación
Autobús Camión:
public class Autobus extends Vehiculo{ public class Camion extends Vehiculo{
public int asientos; public int carga;
public void setAsientos(int a){ public void setCarga(int c){
asientos = a; carga = c;
} }
public int getAsientos(){ public int getCarga(){
return asientos; return carga;
} }
} }
Franco Guidi Polanco 19 Franco Guidi Polanco 20
6. Uso de las clases desarrolladas Una extensión al problema
Entonces una aplicación podría realizar lo Suponga que se desea agregar al sistema un
siguiente: Camión con compartimientos, el cual posee
public class Ejemplo {
patente, marca, carga máxima y una cantidad de
public static void main( String arg[]){ compartimientos. Este camión es capaz de calcular
…
Autobus bus1 = new Autobus();
la capacidad de carga por compartimiento
bus1.setPatente( “AX1313” ); Métodos heredados (equivalente a la carga total, dividida por la
bus1.setMarca( “Mercedes” ); de Vehículo
bus1.setAsientos( 40 ); cantidad de compartimientos). Además provee un
… método que retorna un String de descripción,
Camion cam1 = new Camion();
cam1.setPatente( “BX1515” ); Métodos heredados compuesto por Marca + Cantidad de
cam1.setMarca( “Iveco” ); de Vehículo
compartimientos
cam1.setCarga( 2000 );
…
}
} ¿Qué se debe hacer?
Franco Guidi Polanco 21 Franco Guidi Polanco 22
Análisis Implementación
El Camión con compartimientos es una Camión con compartimientos:
subclase de Camión. public class CamionCompartimientos extends Camion{
public int compartimientos=1;
Vehículo Patente, marca
public void setCompartimientos(int c){
compartimientos = c;
} carga: es
public int getCompartimientos(){ heredado
return compartimientos; (desde
} Camión)
Asientos Autobús Camión Carga
public int getCargaCompartimiento(){
return carga/compartimientos;
} marca: es
public String getDescripción(){ heredado
return marca + compartimientos;
Compartimientos Camión con }
(desde
Vehículo)
compartimientos }
Franco Guidi Polanco 23 Franco Guidi Polanco 24
7. Uso de la nueva clase
public class Ejemplo2 {
public static void main( String arg[]){
…
CamionCompartimientos cam2 = new CamionCompartimientos(); POO en Java IV: Herencia
cam2.setPatente( “CX1818” );
cam2.setMarca( “Ford” );
Métodos heredados
de Vehículo (Parte 3)
cam2.setCarga( 2500 ); Método heredado de Camión
cam2.setCompartimientos( 5 );
System.out.println( cam2.getCargaCompartimiento() ); Franco Guidi Polanco
System.out.println( cam2.getdescripción() ); Escuela de Ingeniería Industrial
…
Pontificia Universidad Católica de Valparaíso, Chile
} fguidi@ucv.cl
}
Actualización: 22 de Agosto de 2011
Franco Guidi Polanco 25
Repaso: extensión de una clase con miembros
Presentación
públicos
Hemos visto:
Los conceptos funamentales asociados a la herencia. public class Persona { public class Alumno extends Persona {
La implementación de subclases en Java, en presencia public String rut; public String rolUCV;
de miembros públicos en la súperclase. public String nombre;
public Alumno() {
Veremos: public Persona() {
rut = "00000000-0"; }
rolUCV = 000000-0";
La implementación de subclases en Java, cuando la nombre = ""; } public void setRolUCV(String r){
public void setRut(String r){ rolUCV = r;
súperclase posee variables de instancia privadas. rut = r; } }
public String getRut(){ public String getRolUCV(){
La relación entre constructores de súperclases y return rut; } return rolUCV;
subclases. public void setNombre(String n){
nombre = n; }
}
public String quiénSoy(){
La relación de las clases con la clase Object. public String getNombre(){
}
return rut + nombre + rolUCV;
return nombre; }
} }
Súperclase Subclase
Franco Guidi Polanco 27 Franco Guidi Polanco 28
8. Miembros heredados (verdad parcial) Miembros no heredados
Una subclase hereda de su súperclase (por el Una subclase no hereda:
momento): Propiedades privadas
Variables de instancia públicas Constructores
Métodos públicos
Los miembros no heredados no pueden aparecer
en el código de la subclase.
Todos los anteriores pueden ser utilizados en la
subclase como si hubieran sido declarados en
ella .
Franco Guidi Polanco 29 Franco Guidi Polanco 30
Miembros no heredados: variables de instancia Miembros no heredados: variables de instancia
privadas privadas
No funciona: Las variables privadas no son heredadas, por lo
public class Persona { public class Alumno extends Persona {
que no pueden aparecer en el código de la
private String rut; private String rolUCV;
subclase.
private String nombre;
public Alumno() {
public Persona() { rolUCV = 000000-0";
rut = "00000000-0"; } Sin embargo se puede hacer uso indirecto de
nombre = ""; }
public void setRut(String r){
public void setRolUCV(String r){
rolUCV = r; ellas en la subclase, a través de los métodos
rut = r; }
public String getRut(){
}
public String getRolUCV(){ públicos de manipulación implementados en la
return rut; }
public void setNombre(String n){ }
return rolUCV;
respectiva súperclase.
nombre = n; } public String quiénSoy(){
public String getNombre(){ return rut + nombre + rolUCV;
return nombre; } }
} }
Error: no pueden ser accesadas directamente
(No compila)
Franco Guidi Polanco 31 Franco Guidi Polanco 32
9. Miembros no heredados: variables de instancia
Miembros no heredados: constructores
privadas
Ejemplo correcto: Los constructores no son heredados, por lo que
public class Persona { public class Alumno extends Persona {
cada subclase debe tener su(s) propio(s)
private String rut; private String rolUCV;
constructor(es).
private String nombre;
public Alumno() { Sin embargo en los constructores se puede invocar
public Persona() {
rut = "00000000-0"; }
rolUCV = 000000-0";
al constructor de la superclase con la instrucción:
nombre = ""; } public void setRolUCV(String r){
public void setRut(String r){ rolUCV = r; }
rut = r; } public String getRolUCV(){
public String getRut(){ return rolUCV; } super( lista parámetros )
return rut; }
public void setNombre(String n){ public String quiénSoy(){
nombre = n; } return getRut() + getNombre()
public String getNombre(){
return nombre; } }
+ rolUCV;
La instrucción super debe ser la primera
} } instrucción del constructor.
Esto sí funciona
Franco Guidi Polanco 33 Franco Guidi Polanco 34
Uso de super en constructores Uso de super en constructores
Ejemplo 1: Ejemplo 2:
public class Persona { public class Alumno extends Persona { public class Persona { public class Alumno extends Persona {
private String rut; private String rolUCV; private String rut; private String rolUCV;
private String nombre; private String nombre;
public Alumno() { public Alumno(String r, String n,
public Persona(String r, String n) { super( 000000-0 , N/A ); public Persona(String r, String n) { String l) {
rut = r; rolUCV = 000000-0"; rut = r; super( r, n );
nombre = n; } nombre = n; rolUCV = l;
} } }
public void setRolUCV(String r){ public void setRolUCV(String r){
public void setRut(String r){ rolUCV = r; } public void setRut(String r){ rolUCV = r;
rut = r; } public String getRolUCV(){ rut = r; } }
public String getRut(){ return rolUCV; } public String getRut(){ public String getRolUCV(){
return rut; } return rut; } return rolUCV;
public void setNombre(String n){ public String quiénSoy(){ public void setNombre(String n){ }
nombre = n; } return getRut() + getNombre() nombre = n; } public String quiénSoy(){
public String getNombre(){ + rolUCV; public String getNombre(){ return getRut() + getNombre()
return nombre; } } return nombre; } + rolUCV;
} } } }
}
Franco Guidi Polanco 35 Franco Guidi Polanco 36
10. Herencia y constructores: la verdad parcial Herencia y constructores
Todo subclase debe incluir una referencia super a algún Dos clases equivalentes:
constructor de la superclase.
public class Alumno extends public class Alumno extends
Persona { Persona {
Si no se incluye la referencia super, Java incluye private String rolUCV; private String rolUCV;
automáticamente una referencia al constructor sin
public Alumno() { public Alumno() {
parámetros de la superclase. Es decir incluye: super(); rolUCV = 000000-0";
super() }
rolUCV = 000000-0"; }
public void setRolUCV(String r){ public void setRolUCV(String r){
Notar que se produce un error cuando no existe un rolUCV = r; }
public String getRolUCV(){
rolUCV = r; }
public String getRolUCV(){
constructor sin parámetros en la superclase y se omite la return rolUCV; } return rolUCV; }
referencia super en la subclase ¿por qué? public String quiénSoy(){ public String quiénSoy(){
return getRut() + getNombre() return getRut() + getNombre()
+ rolUCV; + rolUCV;
} }
} }
Franco Guidi Polanco 37 Franco Guidi Polanco 38
Herencia y constructores: ¡Atención! Herencia y constructores: la verdad total
¿Qué pasa en el siguiente caso? En Java toda clase extiende otra clase.
public class Persona { public class Alumno extends
Las clases que no declaran extender a otras,
Persona { extienden a la clase Object (del package
private String rut;
private String nombre; private String rolUCV; java.lang).
public Persona(String r, String n) {
rut = r;
public Alumno() {
rolUCV = 000000-0";
Object es la superclase (directa o indirecta) de
nombre = n; } todas las clases.
}
public void setRut(String r){
rut = r; } No compila
public void setRolUCV(String r){
rolUCV = r; }
Todas las clases son subclases de Object o de otra
public String getRut(){
Java incluye automáticamente
return rut; }
public String getRolUCV(){
public Alumno() { } subclase.
return rolUCV;
una referencia super(), pero a n){ super();
public void setNombre(String
nombre = n; } public String quiénSoy(){
un constructor inexistente en la rolUCV = 000000-0";
public String getNombre(){
súperclase.nombre; }
return getRut() + getNombre() Por lo tanto: todos los constructores incluyen
return } + rolUCV;
(explícitamente o no) una referencia al constructor de su
}
} } superclase.
Franco Guidi Polanco 39 Franco Guidi Polanco 40
11. Herencia y constructores: la verdad total
Object
Vehículo Persona Bien Raíz POO en Java IV: Herencia
(Parte 4)
Camión Casa Negocio
Alumno Profesor
Franco Guidi Polanco
Escuela de Ingeniería Industrial
Pontificia Universidad Católica de Valparaíso, Chile
fguidi@ucv.cl
Alumno Alumno Profesor
pregrado magíster hora
Actualización: 22 de Agosto de 2011
Franco Guidi Polanco 41
Presentación Ejercicio: Implementar las siguientes clases
Hemos visto: Un videojuego tiene Personajes. Cada personaje tiene un nombre
(String) y un nivel propio de energía (int). Además implementan el
Implementación de jerarquías de herencia con variables método alimentarse, que recibe por parámetro una cantidad de energía
de instancia públicas y privadas. (int) con el que incrementa el nivel propio de energía. Los personajes
Invocación de constructores de súperclases mediante pueden ser:
Guerreros: tienen además un arma (String). Al momento de la
super.
instanciación reciben su nombre, arma y nivel propio de energía
La clase Object como la súperclase de toda jerarquía de inicial. Los guerreros tienen un método combatir que recibe por
herencia en Java. 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
Veremos: el arma y la cantidad de energía del ataque concatenados.
Un ejercicio de desarrollo de una jerarquía de herencia Magos: tienen además un poder (String). Al momento de la
con variables de instancia privadas, y con referencias instanciación reciben su nombre y poder. Los magos son siempre
creados con un nivel propio de energía igual a 100. Proveen un
explícitas a constructor de la súperclase.
método encantar, que disminuye en 2 unidades el nivel propio de
La representación de clases y jerarquías de herencia energía y que retorna el poder del mago.
mediante diagramas de clases de UML.
Franco Guidi Polanco 43 Franco Guidi Polanco 44
12. Análisis y diseño Análisis y diseño
La clase Personaje:
Personaje
- nombre: String
Nombre de la - energía: int
Personaje clase!
+getNombre(): String
+getEnergia(): int
Visibilidad
+alimentarse(energiaNueva:int)
privada (-)! - nombre: String Variables de +consumirEnergia(gastoEnergia:int)
- energía: int instancia! +Personaje(nombre:String, energia:int)
Visibilidad
pública (+)! +getNombre(): String Métodos y
+getEnergia(): int constructores!
+alimentarse(energiaNueva:int)
+consumirEnergia(gastoEnergia:int) Guerrero Mago
+Personaje(nombre:String, energia:int) -arma: String -poder: String
+combatir(energ:int):String
+encantar():String
+Guerrero(nombre:String, energía:int,
+Mago(nombre:String, poder:String)
arma:String)
Los constructores van subrayados!
Franco Guidi Polanco 45 Franco Guidi Polanco 46
Personaje
Implementación Personaje Implementación
- nombre: String
Clase Personaje: - energía: int
Clase Guerrero:
+getNombre(): String Guerrero
public class Personaje{ +getEnergia(): int
+alimentarse(energiaNueva:int) -arma: String
private String nombre; +consumirEnergia(gastoEnergia:int)
+Personaje(nombre:String, energia:int) +combatir(energ:int):String
private int energia; +Guerrero(nombre:String,
energía:int, arma:String)
public Personaje(String nombre, int energia){ public class Guerrero extends Personaje{
this.nombre = nombre;
private String arma;
this.energia = energia; }
public String getNombre(){ public Guerrero(String nombre, int energia, String arma){
return nombre; } super(nombre, energia);
this.arma = arma;
public int getEnergia(){ }
return energia; } public String combatir(int energ){
public void alimentarse(int energiaNueva){ actualizaEnergia( -1*energ );
energia = energia + energiaNueva; } return arma + energ;
}
public void consumirEnergia(int gastoEnerg){
energia = energia - gastoEnerg; } }
}
Franco Guidi Polanco 47 Franco Guidi Polanco 48
13. Personaje
Implementación Uso de las clases
Clase Mago: Mago Ejemplo:
-poder: String
…
+encantar(energ:int):String
+Mago(nombre:String, poder:String)
public class Mago extends Personaje{ Guerrero g1 = new Guerrero(“Alfa”, 50, “Burbujitas de jabón”);
g1.combatir( 2 );
private String poder; System.out.println( “El nivel de energía de ” + g1.getNombre()
+ “ es ” + g1.getEnergia() );
public Mago(String nombre, String poder){
super(nombre, 100); …
this.poder = poder;
} Mago m1 = new Mago( “Harry”, “Quemar” );
public String encantar(){ m1.encantar();
actualizaEnergia( -2 ); System.out.println( “El nivel de energía de ” + m1.getNombre()
return poder; + “ es ” + m1.getEnergia() );
}
…
}
Franco Guidi Polanco 49 Franco Guidi Polanco 50
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
POO en Java IV: Herencia en Java.
(Parte 5) La notación del Diagrama de Clases de UML para clases y relaciones
de herencia.
Franco Guidi Polanco Veremos:
Tratamiento de variables que referencian subtipos.
Escuela de Ingeniería Industrial
Pontificia Universidad Católica de Valparaíso, Chile Sobreescritura de métodos.
fguidi@ucv.cl Uso del operador instanceof para conocer el tipo de un objeto.
Casting en jerarquías de herencia.
Clases con miembros protegidos (protected).
Actualización: 22 de Agosto de 2011
Franco Guidi Polanco 52
14. Referencias, tipos y subtipos Referencias, tipos y subtipos
Una variable de referencia puede Dado que toda clase es subclase directa o indirecta de la
Persona referenciar objetos del mismo tipo de clase Object, una variable de este tipo puede referenciar
la variable (esto ya lo sabíamos). objetos de cualquier tipo. Ejemplos:
Ejemplo:
Object o = new Persona();
Alumno Object o = new Tesista();
Persona p = new Persona();
Object o = new Lavadora();
Tesista Una variable de referencia puede En consecuencia, un arreglo de tipo Object puede
referenciar objetos de cualquier almacenar cualquier tipo de objeto en sus posiciones:
subtipo de la variable. Ejemplos:
Object[] arr = new Object[10];
Persona p = new Alumno(); arr[1] = new Persona();
Persona p = new Tesista(); arr[2] = new Tesista();
arr[3] = new Lavadora();
Franco Guidi Polanco 53 Franco Guidi Polanco 54
Referencias, tipos y subtipos Reconocimiento de clases: operador instanceof
Una variable de referencia de un
Persona determinado tipo NO puede referenciar
El operador instanceof permite reconocer la clase a
objetos de un súpertipo. la que pertenece un objeto referenciado desde una
variable determinada.
Alumno Por lo anterior, las siguientes Formato:
asignaciones NO son válidas: NombreVar instanceof NombreClase
Ejemplo:
Tesista Alumno a = new Persona();
if( pers instanceof Persona )
Tesista t = new Alumno();
System.out.println( La variable pers referencia a una Persona );
Tesista t = new Persona();
else
System.out.println( La variable pers no referencia a una Persona );
Franco Guidi Polanco 55 Franco Guidi Polanco 56
15. Operador instanceof y herencia Operador instanceof: ejemplo
Suponer: Persona p1 =null:
Todo objeto es instancia de la clase a la que
Profesor p2 = new Profesor();
pertenece, como también instancia de su
Alumno p3 = new Alumno();
superclase.
Persona if( p1 instanceof Persona ) --> false!
Electrodoméstico if( p2 instanceof Profesor ) --> true!
Profesor Alumno if( p2 instanceof Persona ) --> true!
Un objeto de la clase lavadora es
if( p2 instanceof Alumno ) --> false!
también un electrodoméstico
Lavadora
if( p3 instanceof Alumno ) --> true!
if( p3 instanceof Persona ) --> true!
if( p3 instanceof Profesor ) --> false!
Franco Guidi Polanco 57 Franco Guidi Polanco 58
Operador instanceof: ejemplo Sobreescritura de métodos
Persona Un método declarado e implementado en una súperclase
puede ser reimplementado en una subclase. Esto se
denomina sobreescritura de métodos.
Alumno Conceptualmente significa que la subclase realiza la misma
Persona personas = new Persona[100];
operación de la súper clase, pero de un modo distinto.
// Supongamos que aquí se ingresan Esto es un caso de polimorfismo.
// al arreglo Personas, Alumnos
// y Tesistas. Tesista public class Persona {
private String rut;
public class Alumno extends
Persona {
…
private String nombre;
public String getRut(){ private String carrera;
//Aquí se muestra la cantidad de tesistas return rut; }
cantidadTesistas = 0; public String getNombre(){ public String identificarse(){
for(int i=0; i< personas.length; i++) return nombre; } return getRut() + getNombre()
public String identificarse(){ + carrera;
if( personas[i] instanceof Tesista ) return rut + nombre; }
cantidadTesistas++; }
System.out.println( “Hay” + cantidadTesistas + “ tesistas”); //otros miembros de la clase… //otros miembros de la clase…
… } }
Franco Guidi Polanco 59 Franco Guidi Polanco 60
16. Sobreescritura de métodos ¿Qué ocurre en las siguientes situaciones?
Consideremos estas clases en los siguientes Persona a = new Persona( 100 , Matías );
System.out.println( a.identificarse() ); 100Matías
ejemplos:
public class Persona { public class Alumno extends 100 Matías public String identificarse(){
Persona { return rut + nombre;
private String rut, nombre; getRut() }
private String carrera;
public Persona(String r, String n){ getNombre()
a
rut = r; public Alumno(String r, String
nombre = n; n, String c){
identificarse()
} super(r,n);
carrera = c;
Alumno b = new Alumno( 100 , Matías , Ind );
public String getRut(){
return rut;
}
System.out.println( b.identificarse() ); 100MatíasInd
} public String identificarse(){
public String getNombre(){ return getRut() + getNombre() public String identificarse(){
return nombre; + carrera; 100 Matías Ind return getRut() +
} } getNombre() +
public String identificarse(){ getRut() carrera;
}
return rut + nombre; }
getNombre()
b
}
}
identificarse()
Franco Guidi Polanco 61 Franco Guidi Polanco 62
¿Qué ocurre en la siguiente situación? Sobreescritura de métodos
public class Persona { public class Alumno extends
Persona a = new Alumno( 100 , Matías , Ind ); private String rut, nombre; Persona {
System.out.println( a.identificarse() ); 100MatíasInd public Persona(String r, String n){
rut = r; nombre = n;
private String carrera;
public Alumno(String r, String
} n, String c){
public String getRut(){ return rut;} super(r,n); carrera = c;
public String identificarse(){ public String getNombre(){ }
100 Matías Ind return getRut() +
return nombre;} public String identificarse(){
public String identificarse(){
public String identificarse(){ return getRut() + getNombre()
return getRut() + getNombre()
getRut() getNombre() + return rut + nombre; + carrera;
+ carrera;
carrera; } }}
getNombre() } } }
a identificarse()
Persona a = new Alumno( 100 , Matías , Ind );
Java resuelve en tiempo de ejecución la asociación entre la System.out.println( a.identificarse() ); 100MatíasInd
variable de referencia y el método que debe invocar, en
función del objeto que se encuentre referenciado en ella.
Franco Guidi Polanco 63 Franco Guidi Polanco 64
17. Sobreescritura de métodos Herencia y acceso a miembros de una clase
public class Persona { public class Alumno extends
Persona a = new Alumno( 100 , Matías , Ind ); private String rut; Persona {
System.out.println( a.identificarse() ); private String nombre;
public setDatos(String r, String n) { private String carrera;
rut = r;
nombre = n; } public String matricularse(
El compilador Java es responsable de verificar que public String getRut(){
return rut; } carrera = c;
String c){
el método pertenezca al tipo de dato declarado por public String getNombre(){
return nombre; }
}
la variable. } }
El intérprete Java es responsable de identificar y
Esto debe funcionar:
ejecutar la implementación del método
correspondiente al tipo de objeto referenciado en Persona a = new Persona();
a.setDatos( “1000-2”, “Luis”);
el momento por la variable.
Alumno b = new Alumno();
b.setDatos( “2000-3”, “Pamela” );
b.matricularse( “Industrial” );
Franco Guidi Polanco 65 Franco Guidi Polanco 66
Herencia y acceso a miembros de una clase Casting
public class Persona { public class Alumno extends public class Persona { public class Alumno extends
private String rut; Persona { private String rut; Persona {
private String nombre; private String nombre;
public setDatos(String r, String n) { private String carrera; public setDatos(String r, String n) { private String carrera;
rut = r; rut = r;
nombre = n; } public String matricularse( nombre = n; } public String matricularse(
public String getRut(){ String c){ public String getRut(){ String c){
return rut; } carrera = c; return rut; } carrera = c;
public String getNombre(){ } public String getNombre(){ }
return nombre; } return nombre; }
} } } }
¿Esto funciona? Error: el compilador
Es necesario introducir un casting para indicar al
determina que este método compilador que el objeto referenciado en la variable es
Persona c = new Alumno(); no pertenece a Persona. Sin efectivamente una instancia de Alumno:
c.setDatos( “1000-2”, “Luis”); embargo la variable contiene
c.matricularse( “Comercial” ); referencia a un Alumno, que es
un tipo de Persona (y que posee Persona c = new Alumno();
este método). c.setDatos( “1000-2”, “Luis”);
( (Alumno)c ).matricularse( “Industrial” );
Franco Guidi Polanco 67 Franco Guidi Polanco 68
18. Casting Miembros protegidos de una clase
El casting no convierte objetos, simplemente El modificador de visibilidad protected, permite
explicita el tipo de objeto referenciado en una declarar visibilidad “protegida” en variables de
variable. instancia y métodos.
Persona a = new Profesor();
Profesor b = a; // ERROR Los miembros de una clase con visibilidad
Persona Persona a = new Profesor(); protegida son sólo accesibles desde la misma clase
Profesor b = (Profesor) a;
Alumno c = (Alumno) a;
// OK
// ERROR
o desde cualquier subclase de ella (no son
accesibles desde otras clases).
Profesor Alumno Persona a = new Persona();
Profesor b = (Profesor) a; // ERROR
Alumno c = (Alumno) a; // ERROR
Alumno a = new Alumno();
Profesor b = (Profesor) a; // ERROR
Franco Guidi Polanco 69 Franco Guidi Polanco 70
Miembros protegidos de una clase Miembros protegidos de una clase
Por lo tanto, una subclase hereda de su Ejemplo:
superclase: public class Persona { public class Alumno extends
Persona {
Variables de instancia protegidas y públicas protected String rut;
protected String nombre; private String rolUCV;
Métodos protegidos y públicos
public Persona(String r, String n) { public Alumno() {
rut = r; super( 000000-0 , N/A );
nombre = n; rolUCV = 000000-0";
} }
public void setRut(String r){
rut = r; } public String quiénSoy(){
public String getRut(){ return rut + nombre
return rut; } + rolUCV;
public void setNombre(String n){ }
nombre = n; } }
public String getNombre(){
return nombre; }
}
Franco Guidi Polanco 71 Franco Guidi Polanco 72
19. 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
POO en Java IV: Herencia atributos, todos ellos disponen de
código, sello discográfico y autor. ProductoMusical
(Parte 6) Se desea evitar duplicidad de
código.
código
sello
autor
Franco Guidi Polanco Decisión: se determina la
conveniencia de crear la clase
Escuela de Ingeniería Industrial “ProductoMusical”, que agrupa las
Pontificia Universidad Católica de Valparaíso, Chile propiedades comunes de los tres
tipos de productos. CD DVD Vinilo
fguidi@ucv.cl
La superclase aparece por factorización
de propiedades comunes
Actualización: 22 de Agosto de 2011
Franco Guidi Polanco 74
Clases abstractas Clases abstractas
En el ejemplo anterior la clase ProductoMusical es abstracta (no Otro ejemplo: un software trabaja con distintas
representa entidades presentes en el dominio).
figuras geométricas, todas ellas polígonos, con
Esta condición se explicita en el diseño, declarando la clase como
abstracta. algunas propiedades en común (ej. cantidad de
lados).
public abstract class ProductoMusical {
ProductoMusical
{abstract} private int código;
código
private String sello;
Polígono
sello ...
autor
}
CD DVD Vinilo
Una clase abstracta no puede ser instanciada, ha sido diseñada sólo
para ser extendida.
Franco Guidi Polanco 75 Franco Guidi Polanco 76
20. Clases abstractas Métodos abstractos
public abstract class Poligono { Supongamos que en el ejemplo
protected int lados; anterior todos los polígonos deben
public void setLados(int l){ proveer un método de cálculo de área.
Polígono lados = l; Polígono
} 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:
public class Cuadrado extends Poligono { lado2, área de triángulo base * altura /2,
private int longitud; etc.), por lo tanto no puede establecerse
public void setLongitud(double l) { una lógica común a nivel de superclase.
longitud = l;
} Solución: declarar método como
... abstracto en la superclase.
}
Franco Guidi Polanco 77 Franco Guidi Polanco 78
Métodos abstractos Métodos abstractos
public abstract class Poligono {
Un método abstracto es un método que se declara protected int lados;
en una superclase, pero sin proveer public int setLados(int l){
lados = l;
implementación. }
public abstract double getArea();
La implementación de un método abstracto se Polígono ...
difiere para sus subclases. }
Una clase que declara uno o más métodos
public class Cuadrado extends Poligono {
abstractos es necesariamente abstracta (y debe private double longitud;
ser declarada como tal). public void setLongitud(double l) {
longitud = l;
Si una subclase no provee implementación para un }
public double getArea(){
método abstracto que hereda de su superclase, es return longitud*longitud;
necesariamente abstracta (y debe ser declarada }
...
como tal). } 80
Franco Guidi Polanco 79 Franco Guidi Polanco 80
21. 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:
Polígono figura = new Triángulo(); getArea() fue
declarado como
método abstracto
double sup = figura.getArea(); en Polígono.
Franco Guidi Polanco 81