Lecc5 Herencia Con Anotaciones
-
Upload
pedroramos -
Category
Documents
-
view
212 -
download
0
Transcript of Lecc5 Herencia Con Anotaciones
-
8/20/2019 Lecc5 Herencia Con Anotaciones
1/11
Lección 5. Herencia
1
La herencia en Java es el mecanismo por el una clase se define extendiendo otraexistenteclass Madre{
}
class Hija1 extends Madre{ … class HijaN extends Madre{
+ +
+ +
} }
Clase original: madre, padre, extendida, base, superclase, …
Nueva clase: hija, heredada, subclase, …
Sólo puede extenderse una clase: herencia simple.
La nueva clase puede ser extendida por otras. Será subclase y superclase.
El conjunto de clases relacionadas por herencia forma una jerarquía de clases.
Una subclase hereda de todas sus superclases (su madre y resto de ascendientes).
Una clase declarada como final (final class …) no puede extenderse.
Todas las clases de una jerarquía funcionan como clases independientes, y pueden referenciarseentre sí. Una clase puede, incluso, referenciar a sus descendientes.
Las subclases contienen los atributos y métodos privados de las superclases, pero no puedenusarlos.
Lección 5. Herencia
public class Novela extends Libro{
String autor;
String género;
int preciorecomendado;
int edición;
public Novela(String tit, String aut){
título = tit;
autor = aut;
}
public String toString(){ // ya existía en Libro, pero puede
// rehacerse o sobreescribirse
return título + “\n” + autor + “\n” +
género + “\n” + “edición: ” + edición;
}
public void ponPrecio(int p){
preciorecomendado = precio;
}
//…
Lección 5. Herencia
-
8/20/2019 Lecc5 Herencia Con Anotaciones
2/11
Lección 5. Herencia
2
Acceso a miembros de una clase. Modificadores de acceso.
private [friendly]* protected public
------------------------------------------------------------------------------------------------
Misma clase sí sí sí sí
Subclase del mismo paquete no sí sí sí
No subclase del mismo paquete no sí sí sí
Subclase de diferente paquete no no sí sí
No subclase de diferente paquete no no no sí
*friendly = package; no se indica expresamente, sino por la ausencia de los otros.
O bien (mas resumido):
Clase Paquete Subclase CualquierSitio
----------------------------------------------------------------------
public si si si si
protected si si si no
si si no no
private si no no no
Las clases sólo pueden ser public o friendly
Lección 5. Herencia
package p1 package p2
C clase pública
con elementos… Accesibles en…
-----------------------------------------------------------------------------------------------------------
public: todas la clases (incluso ascendientes)
protected: su paquete y otros descientes
[friendly]: su paquete
private: su clase
Lección 5. Herencia
C
C
C
C
C
-
8/20/2019 Lecc5 Herencia Con Anotaciones
3/11
Lección 5. Herencia
3
Sobreescritura y polimorfismo Una subclase puede sobreescribir (reimplementar, reescribir, …) alguno de los métodos de
su(s) superclase(s) (también los atributos, pero no tiene mucho sentido y no suele hacerse).
El método sobreescrito debe respetar el nombre y los parámetros; la salida puede sersubclase de la original, y el modificador de acceso no puede ser mas restrictivo (pero sí masgeneral: puede ponerse public en vez de private, etc.).
Si no se sobreescribe, se ejecutará la versión de la superclase mas cercana.
La propiedad de que un método pueda tener varios comportamientos, según su clase, sellama polimorfismo.
Un método declarado como final no puede sobreescribirse.
class Persona{ Persona juan = new Persona();
… Empleado luis = new Empleado();
void saludo(){ Profesor ana = new Profesor();
System.out.println(“Soy una persona”);
} juan.saludo() ---> “Soy una persona”
juan = new Empleado(); // un Empleado es Persona
class Empleado extends Persona{ juan.saludo() ---> “Soy un empleado;
…
void saludo(){
System.out.println(“Soy un empleado”); luis.saludo() ---> “Soy una persona” // sin reesc.
} ---> “Soy un empleado” // con reesc.
class Profesor extends Empleado{
… ana.saludo() ---> “Soy una persona” // según
void saludo(){ ---> “Soy un empleado” // donde se
System.out.println(“Soy un profesor”); ---> “Soy un profesor” // reescriba
}
Lección 5. Herencia
Ligadura dinámica
El código ejecutable de un método se decide en tiempo de ejecución, y no en tiempo decompilación. Por ejemplo: supongamos el siguiente método que usa la clase Persona:
void muestraSaludo(Persona p){
p.saludo();
}
Cuando se compila, no se sabe qué se ejecutará en la línea p.saludo(). Quedapendiente para cuando se ejecute. Según la llamada
muestraSaludo(juan); muestraSaludo(luis); muestraSaludo(ana);
podrá tener diferentes respuestas.
Otro ejemplo:
Persona presidente;
presidente = luis; presidente.saludo(); // luis es Empleado
presidente = ana; presidente.saludo(); // ana es Profesor
// el código que se ejecutará se decide en tiempo de ejecución,
// viendo el contenido de presidente.
Otro ejemplo típico son los métodos toString() y equals() de cualquier clase. Losobjetos se muestran o comparan según la última clase que los sobreescribe (empezandodesde Object).
Lección 5. Herencia
-
8/20/2019 Lecc5 Herencia Con Anotaciones
4/11
Lección 5. Herencia
4
super(…)Con super()podemos invocar a los atributos y constructores de la superclase.
public Novela(String tit, String aut){
super(tit); // se crea como un Libro.
autor = aut;
}
Importante: La primera línea de cualquier constructor siempre debe ser una llamada asuper(…)(directa o indirectamente a través de this(…)). Si no se pone nada, sesupone que es super(), por lo que la superclase deberá tener este constructor.
super
Con super podemos invocar a atributos y métodos de la superclase, como si no sehubiera extendido.
public toString(){
return super.toString() + “\n” + autor + “\n” + “Género: Novela”;
// se llama al método toString() de los libros.
}
Si no usarmos super se entiendo que es this, y sería una llamada recursiva (infinita).
Vemos que resulta útil para poder llamar en una subclase métodos que han sidosobreescritos.
Lección 5. Herencia
Sobreescritura y sobrecarga.
Como vimos en la lección 3, en Java podemos implementar métodos y constructores conel mismo nombre. Decíamos que el método o constructor estaba sobrecargado.
No debemos confundir sobrecarga con sobreescritura.
Si queremos sobreescribir un método heredado, pero no respetamos los parámetrosestaremos sobrecargando en vez de sobreescribiendo.
Ejemplos:
public String toString(String s);
// añadimos un nuevo parámetro -> sobrecarga
public boolean equals(Novela n) ;
// ponemos Novela n en vez de Object o -> sobrecarga
// sólo se usará esta versión si se pasa un parámetro declarado
// como Novela (no bastará con contenerlo; p.e. Libro l=new Novela(…))
Recordemos las restricciones sobre la salida en sobreescritura: modificadores de ámbitoiguales o mas generales, y salida igual o una subclase de la original.
public Object toString()
// intento fallido de sobreescribir: Object no es subclase de String
// tampoco es sobrecarga, pues sólo se diferencian en la salida
public Libro clone(){…}
// sobreescritura. El original es protected Object clone()
Lección 5. Herencia
-
8/20/2019 Lecc5 Herencia Con Anotaciones
5/11
Lección 5. Herencia
5
Upcasting y Downcasting. Casting
Es el mecanismo de adaptación de un objeto cuando se asigna a otro de su misma
rama jerárquica.
Supongamos, por ejemplo, las clases Libro con una subclase Novela (u otra
subclase indirecta, como Cuento extends Novela) y los objetos
Libro l;
Novela n;
¿Qué ocurre si hacemos las asignaciones l = n o n = l ?.
O, lo que es igual, si tenemos dos métodos:
String verTítulo(Libro lib);
String verGénero(Novela nov);
¿Qué ocurre si hacemos las llamadas verTítulo(n) y verGénero(l)?
(obsérvese que se trata también de dos asignaciones: lib = n y nov = l).
Vemos que, en general, hay dos casos: l = n y n = l
Lección 5. Herencia
UpCasting: l = n . Asignamos una novela a un libro. Bien.
Siempre es posible. Como n es Libro (además de Novela) no hay problema. La clasede n es un caso particular de la clase de l.
En Java, una asignación x=y cualquiera es correcta si y es un caso particular de x.
Ojo: l sigue siendo de la clase Libro. Con ‘l.’ sólo tenemos acceso a los elementos de
la clase Libro, y no a los exclusivos de Novela. Por ejemplo, no es posible hacer
l.género, pues género es exclusivo de Novela. Tendríamos que hacer((Novela)l).género (ver a l como si fuera Novela).
DownCasting: n = l. Asignamos un libro a una novela. Mal (?). A veces posible.
En general no es posible, pues un libro no siempre es una novela. Tendremos un error encompilación. Pero si estamos seguros que l, a pesar de estar declarado como libro,contiene una novela, podemos indicárselo al compilador de la forma:
n = (Novela)l; // cast o casting de l
Pero, si en tiempo de ejecución l no contiene una novela, tendremos un error de casting .
Ojo: n y l siguen siendo de sus respectivas clases. La expresión (SubClase)obj no
cambia a obj de clase; sólo es un aviso al compilador que de obj contiene un objeto de
la subclase SubClase
Lección 5. Herencia
-
8/20/2019 Lecc5 Herencia Con Anotaciones
6/11
Lección 5. Herencia
6
Ejemplos
Libro libro1 = new Libro(“Recetas de cocina”),
libro2 = new Novela(“Eso”, “S. King”); // bien; upcasting
System.out.println(libro2.género); // error c; libro2 no es novela (género sólo Novela)
System.out.println(((Novela)libro2).género); // bien; libro2 contiene una novela
System.out.println(((Novela)libro1).género); // error e; libro1 no contiene una novela
Novela nov;
nov = new Libro(“Agenda2011”); // error c; un libro no es una novela;
nov = (Novela) new Libro(“Agenda2011”) // error e; el casting no cambia un objeto de clase
nov = libro2; // error c; libro2 contiene una novela, pero el
// compilador no lo sabe (downcasting incorrecto)
nov = (Novela) libro2; // bien; el compilador queda informado, y en tiempo// de ejecución se confirma
nov = (Novela) libro1; // error e; el compilador queda informado, pero en la
// ejecución se ve que libro1 no contiene una novela
---
error c: error en tiempo de compilación
error e: error en tiempo de ejecución
Lección 5. Herencia
El operador instanceof
Es un operador booleano que se utiliza de la forma o instanceof C, donde o es un objeto yC una clase, y devolverá true si o contiene un objeto de clase C, y false en caso contrario.
Ejemplos:
Libro libro1 = new Libro(“Recetas de cocina”);
Libro libro2 = new Novela(“Eso”, “S. King”);
Novela nov = new Novela(“El jugador”);
libro1 instanceof Libro; // true
libro1 instanceof Novela; // false
libro1 instanceof String; // false
libro2 instanceof Libro; // true
libro2 instanceof Novela; // true (contiene una Novela)
nov instanceof Libro; // true (toda Novela es Libro)
nov instanceof Novela; // true
Recordemos el método equals de la clase Libro. Puede completarse así:
public boolean equals(Object o){
return (o instanceof Libro) && título.equals(((Libro)o).verTítulo())
}
Si esto es falso, se evita un error de casting y se devuelve false.
Lección 5. Herencia
-
8/20/2019 Lecc5 Herencia Con Anotaciones
7/11
Lección 5. Herencia
7
La clase Object
Es una clase de la que desciende cualquier clase en Java.
Cuando se declara una clase implícitamente siempre existe extends Object(pero no cuenta para poner otro extends explícito).
Por tanto, sus métodos los contendrá cualquier objeto. Por ejemplo:
public boolean equals(Object o) // ya comentado
public String toString() // ya comentado
public Class getClass()
// Obtiene la clase a la que pertenece el objeto.
// La salida es un objeto especial de clase Class
protected Object clone()
// Clona un objeto, devolviendo otro idéntico.
// Al ser protected, cualquier nueva clase en la// que se quiera permitir la clonación debe
// sobreescribirlo y hacerlo público, o sólo es
// posible usar la versión de la(s) superclase(s)
protected void finalice()
// se explica un poco a continuación
Lección 5. Herencia
protected void finalize()
// Es llamado por el recolector de basura de Java, antes de liberar
// la memoria de un objeto que deja de estar referenciado
// Se utiliza para hacer ciertas gestiones antes de que el objeto
// desaparezca.
Ejemplo: En la clase Libro podemos implementar:
public void finalize(){ // o protectedcantidadDeLibros--; // variable estática con libro creados
System.out.println(“Se ha liberado un objeto. Quedan ” + cantidadDeLibros);
}
Si probamos:
Libro libro1 = new Libro(“Uno"), libro2 = new Libro(“Dos");
libro2 = libro1; // desaparece antiguo libro2
libro1 = new Libro("Tres"); // no desaparece nada (antiguo libro1 en libro2)
libro1 = libro2; // desaparece antiguo libro1
System.gc(); // Llamada expresa al recolector (sin esperar a que
// lo haga Java de forma automática)
Tendremos dos mensajes “Se ha liberado un objeto. Quedan: …”
Lección 5. Herencia
-
8/20/2019 Lecc5 Herencia Con Anotaciones
8/11
Lección 5. Herencia
8
Clases abstractas
A veces el diseño de una clase debe quedar incompleto por varias razones, y nopueden construirse objetos hasta que no se completen. En estos casos, la clasepuede declararse abstracta
abstract class NombreClase {…}
En una clase abstracta determinados métodos pueden quedar sin implementar,indicando sólo su signatura (prototipo). También deben declararse abstractos
abstract unMétodoAbstacto()
Una clase abstracta no se puede instanciar (crear objetos con new), pero sí sepueden referenciar (declarar objetos y usar sus elementos).
Deben completarse creando una subclase que la extienda, en la que debenimplementarse los métodos que falten (además de poder reescribir otros).
No se pueden declarar métodos estáticos abstractos ni constructores abstractos.
Lección 5. Herencia
Ejemplo
abstract class Trabajador {
String nombre, categoria;
int sueldoBase;
Trabajador(String nomb,String categ, int sb) {
nombre=nom;
categoria=cat;
sueldoBase=sb;
}
abstract int calcularSalario(); // método abstracto; no se implementa
void muestraAtributos(){ // método no abstracto
System.out.println("Nombre: " + nombre);
System.out.println("Categoria: " + categoria);
System.out.println("Sueldo Base: "+ sueldoBase);
}
}
// Ejemplo de uso:
Trabajador maría = new Profesor(“María”);
// Se supone que la clase Profesor extiende e implementa Trabajador
Lección 5. Herencia
-
8/20/2019 Lecc5 Herencia Con Anotaciones
9/11
Lección 5. Herencia
9
Interfaces
Sintácticamente son como las clases abstractas, pero con todos los métodosabstractos. Se declaran usando la palabra interface en vez de class:
interface NombreInterfaz {…}
Se implementan como las clases abstractas, usando implements en vez de extends,con la importante diferencia de que una misma clase puede implementar variasinterfaces, incluso aunque extienda otra clase: herencia múltiple
class UnaClase [extends Superclase] implements Intefaz1, Interfaz2, …{}
Normalmente se utilizan para declarar ciertas propiedades que deberán tener futurasclases. Por ejemplo, la interfaz Comparable de Java contiene el métodocompareTo() para comparar objetos de futuras clases. Si declaramos
class Miclase implements Comparable
estamos obligados a implementar en la clase el método int compareTo(Object o),para saber cuando un objeto de Miclase es menor, igual o mayor que otro.
Si tuviéramos un método como void ordena(Comparable v[]), que ordena unvector de objetos comparables, podríamos ordenar un vector de objetos de Miclase,comparándolos según se haya decidido al implementar compareTo.
Lección 5. Herencia
Propiedades de las interfaces
• Una interfaz no se puede instanciar.
• Se pueden definir atributos. Serán considerados como estáticos (static) y finales (final)
• Los métodos de una interfaz son públicos por defecto, luego la implementación deberá ser
pública.
• Un interfaz sólo admite modificadores public y por defecto.
• Si una clase no implementa todos los métodos definidos en una interfaz debe declararse
abstracta
• Se pueden extender. Se pueden crear jerarquías de interfaces.
• Una clase puede implementar más de una interfaz.
• Una interfaz no puede tener constructores. Pero en Java se permite usar el nombre como
un constructor de una clase anónima, de la forma:
unaObjeto = new unaInterface(){ … … };
Clase anónima
Lección 5. Herencia
-
8/20/2019 Lecc5 Herencia Con Anotaciones
10/11
Lección 5. Herencia
10
Ejemplo
interface Comparable{ // ya existe en java.lang
int compareTo(Object o);
}
class Libro implements Comparable{
…
…
public int compareTo(Object o) // Los Strings también son comparables
{ // según orden lexicográfico (diccionario)
if (o instanceof Libro)
return this.título.compareTo(((Libro)o).título);
else
return false;
}
…
}
Lección 5. Herencia
Objetos en los parámetros
Si un parámetro de un método es un objeto, cuando se llama se sigue la misma regla de
casting que en las asignaciones (de hecho, son asignaciones).
Por ejemplo:
Libro lib = …
Novela nov = …
lib.equals(nov); // se hace o=nov, donde o es parámetro de equals
nov.equals(lib); // o=lib
public String verAutor(Novela n) { // supong. fuera de la clase Novela
return n.autor;
}
String a = verAutor(nov); // correcto; se hace n=nov;
String b = verAutor(lib); // incorrecto; se hace n=lib (downcasting).
Lección 5. Herencia
-
8/20/2019 Lecc5 Herencia Con Anotaciones
11/11
Lección 5. Herencia
Devolución de objetos
Si en un método comparamos la clase del objeto devuelto con la clase declarada en
la signatura (prototipo), ocurre algo similar.
Csalida metodo(…){ devuelve un objeto de la clase Csalida
…
return x; // x debe ser de clase Csalida o una subclase
}
Como si asignáramos x a un objeto de clase Csalida:
Csalida y = metodo(…); // equivale a y = x;
Por lo tanto, x debe ser de una subclase de la de y (upcasting)
(o de clase Csalida)
Lección 5. Herencia
Ejercicios
1. Implementar la clase Alumno, que extiende la interfaz Persona. Incluir un atributo con un vectorde profesores, y métodos para incluir y mostrar profesores.
2. Implementar el método clone() en la clase Persona de dos formas: a) creando expresamenteun objeto que clona a this, y b) clonando con super.clone() (debe implementarse la interfazCloneable). Poner ejemplos de uso para clonar objetos Persona y descendientes. Quédiferencia hay entre las dos versiones?
3. Clonar un alumno y comprobar su lista de profesores. Añadir un profesor al alumno clonado ycomprobar que también se ha añadido al original. Hacer las correcciones necesarias para que noocurra esto (una vez hecha la clonación, cada objeto evoluciona de forma independiente).
4. ¿Es posible que Persona tenga un atributo de clase Profesor? Probarlo.
5. Implementar la Interfaz Docente con los métodos int horas(), que informa de las horas dedocencia semanales, y boolean ponHorario(String día, int horas), que anota elhorario de un docente, devolviendo false si se pasa del máximo. Esta interfaz es implementadapor las clases Profesor y Alumno, cada uno con 3 y 8 horas semanales como máximo.Implementar un método en la clase principal que obtiene la media de horas de un ventor dedocentes. Aplicarlo para un vector con varios alumnos y profesores.
6. Indicar dos formas de conseguir que Alumno y Profesor también implementen la interfazComparable de Java. Implementar una de ellas, donde compareTo() se implementa usando elmétodo horas().
7. Implementar en la clase principal un método para obtener el mayor elemento de un vector decomparables, según el método compareTo() (no debe hacerse referencia a Docente).
8. Modificar la clase Fracción para que implemente la interfaz Comparable de Java. ¿Podríaaplicarse el método del punto anterior para un vector donde se mezclan docentes y fracciones?
9. [ Implementar la interfaz ComparableTotal, que extiende la interfaz Comparable de Java,incorporando un nuevo método double toDouble(), que obtiene un valor asociado a cadaobjeto, y que se usará para implementarcompareTo(). ]
10. [ Repetir los puntos 4, 5 y 6 usando ComparableTotal, en vez de Comparable. ]
Lección 5. Herencia