Lecc5 Herencia Con Anotaciones

download Lecc5 Herencia Con Anotaciones

of 6

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