Documente Academic
Documente Profesional
Documente Cultură
Manejando Herencias
Traduccin: Lucas Videla Fuente: Tutora de http://java.sun.com/docs/books/tutorial/java/javaOO/subclasses.html La clase Object, definida en el paquete java.lang, define e implementa comportamiento comn a todos los objetos. Como se muestra en la siguiente imagen, muchas clases derivan de Object, muchas clases derivan de esas clases, y as sucesivamente, formando una jerarqua de clases.
Todas las clases son descendientes de Object En la cima de la jerarqua, Object es la ms general de todas las clases. Las clases cerca de la base de la jerarqua proveen un comportamiento ms especializado. Una subclase deriva de otra clase. El trmino superclase se refiere al ancestro directo de una clase, o a cualquiera de sus clases ascendentes. Cada clase tiene una y slo una superclase directa (herencia simple). Una subclase hereda todas las variables y mtodos miembro de su superclase. Sin embargo, la subclase puede no tener acceso a una variable o mtodo heredado. Por ejemplo, una subclase no puede acceder a un miembro privado heredado de su superclase. Uno podra pensar, entonces, que este tem no fue heredado en absoluto. Pero el tem es heredado. Esto se convierte en importante cuando se usa una clase interna (ya se ver el concepto), la cual tiene acceso a los miembros privados de la clase que la incluye. Ntese que los constructores no son miembros y por lo tanto no son heredados por subclases.
Sobreescribiendo mtodos
Un mtodo de instancia en una subclase con la misma firma y tipo de retorno que el mtodo de instancia de la superclase sobreescribe el mtodo de la superclase (Record que la firma de un mtodo es el nombre y el nmero y tipo de parmetros). La habilidad de una subclase para sobreescribir un mtodo le permite a la clase heredar desde una superclase aqul comportamiento que es suficientemente cercano y luego modificar el comportamiento com sea necesario. Por ejemplo, la clase Object contiene un mtodo de instancia llamado toString que devuelve una cadena representando la instancia de ese tipo. Cada clase hereda este mtodo. La implementacin en Object no es muy til para las subclases; entonces, recomendamos sobreescribir este mtodo para preveer mejor informacin para tus clases. Es particularmente til para debuguear (quitar errores). Aqu hay un ejemplo de sobreescritura del toString: public class MiClase { private int unEntero = 4; //Sobreescribimos el mtodo toString public String toString() { return "Instancia de MiClase. unEntero = " + unEntero; } } El mtodo que sobreescribe tiene el mismo nombre, nmero y tipo de argumentos, y devuelve un valor del mismo tipo que el mtodo que est sobreescribiendo (de hecho, el tipo que devuelve una subclase puede ser una subclase del tipo que devuelve la superclase. Pero ese es otro tema). El mtodo que sobreescribe puede tener diferentes throws (lanzamientos de excepciones) en su definicin mientras no especifique ningn tipo no especificado en la clusula throws del mtodo sobreescrito. Adems, el especificador de acceso para el mtodo que sobreescribe puede admitir ms pero no menos acceso que el mtodo sobreescrito. Por ejemplo, un mtodo protegido en la superclase puede ser pblico pero no privado en la subclase. Una subclase no puede sobreescribir mtodos declarados como final en la superclase (por definicin, los mtodos final no pueden ser sobreescritos). Ya veremos cmo escribir mtodos final. Una subclase debe sobreescribir los mtodos que son declarados como abstractos en la superclase, o la subclase asimismo ser abstracta. El tema de clases abstractas se dar en otra oportunidad. Tambin se puede hacer lo que se conoce como sobrecargar mtodos, mediante la escritura de nuevos mtodos que tengan distinto nmero o tipo de argumentos. Adems se pueden sobrecargar mtodos en una superclase. Aqu hay un ejemplo de sobrecarga del mtodo toString. public class MiClase { private int unEntero = 4; //Sobreescribimos el mtodo toString public String toString() { return "Instancia de MiClase. unEntero = " + unEntero; } //Sobrecargamos el mtodo toString public String toString(String prefijo) { return prefijo + "Instancia de MiClase. unEntero = " + unEntero; } }
Como ilustra el ejemplo anterior, se debe sobrecargar un mtodo de una superclase para proveer funcionalidad adicional. Cuando se escribe un mtodo que tiene el mismo nombre que en la superclase, se debe chequear doblemente los valores de retorno y listas de argumentos para estar seguro si se est sobrecargando o sobreescribiendo, lo que se hubiera pretendido. Por ltimo, debemos destacar que un mtodo de instancia no puede sobreescribir a un mtodo de clase, y un mtodo de clase no puede sobreescribir un mtodo de instancia. La siguiente tabla resume qu sucede cuando se define un mtodo de la misma firma que un mtodo en una superclase: Mtodo de Instancia en Superclase Mtodo de Instancia Mtodo de Clase Sobreescribe Genera un error en tiempo de compilacin Mtodo de Clase en Superclase Genera un error en tiempo de compilacin Esconde el mtodo
Utilizando super
Si tu mtodo sobreescribe uno de los mtodos de su superclase, an pods invocar el mtodo sobreescrito mediante el uso de super. Adems pods usar super para referirte a una variable miembro escondida. Consideremos esta superclase: public class Superclase { public boolean unaVariable; public void unMetodo() { unaVariable = true; } } Ahora, aqu est la subclase, que sobreescribe el mtodo y la variable: public class Subclase extends Superclase { public boolean unaVariable; // esconde unaVariable en Superclase public void unMetodo() { unaVariable = false; super.unMetodo(); System.out.println(unaVariable); System.out.println(super.unaVariable); } } Dentro de la Subclase, el nombre unaVariable se refiere a la que est declarada en la Subclase. De manera similar, el nombre unMetodo se refiere al que est declarado dentro de la Subclase, el cual sobreescribe al de la Superclase. Entonces, para referirse a unaVariable y a unMetodo heredados desde la Superclase, la Subclase debe usar una palabra reservada, super, como se mostr. Luego, la salida de la invocacin al mtodo unMetodo de la Subclase muestra lo siguiente: false true El siguiente ejemplo muestra cmo usar la palabra reservada super para invocar al constructor de la superclase. Supon que ests escribiendo un sistema basado en transacciones y necesits arrojar una excepcin si la transaccin falla. Como una excepcin debe inclur un mensaje informativo y una referencia a la causa del problema, otra excepcin, chequeada o no chequeada (Throwable). public final class TransactionFailedException extends Exception { static final long serialVersionUID = -8919761703789007912L; public TransactionFailedException(Throwable cause){ super(Transaction failed,cause); } } La lnea en negrita es una invocacin explcita al constructor de la superclase, que llama al constructor provisto por la clase Exception. Exception tiene cuatro constructores, y este en particular invoca a la versin que toma como argumentos una cadena y un Throwable. Si est presente, la invocacin explcita al constructor de la superclase debe ser la primera instruccin en el constructor de la subclase. Si un constructor no invoca explcitamente al constructor de la superclase, el compilador de Java automticamente inserta una llamada al constructor sin argumentos de la superclase.
Nota: El mtodo clone no debe nunca usar new para crear un clon y no debe llamar a constructores. En cambio, el mtodo debe llamar a super.clone, el cual crea un objeto del tipo correcto y permite a la jerarqua de superclases realizar la copia necesaria para obtener un clon adecuado. Los mtodos equals y hashCode El mtodo equals compara dos objetos por igualdad y devuelve verdadero si son iguales. El mtodo provisto por la clase Object usa el operador de identidad (==) para determinar cundo dos objetos son iguales. Si los objetos comparados son exactamente el mismo objeto, el mtodo devuelve verdadero. Sin embargo, para algunas clases, dos objetos distintos de un tipo en particular deben ser considerados iguales si contienen la misma informacin. Aqu hay un ejemplo: Supongamos que tenemos varias instancias de Libro, los cuales tienen entre sus atributos el ISBN, nombre, autor, precio, ubicacin... los datos tpicos que tendra en una librera. Ahora bien, dos libros son iguales si sus ISBN son iguales (as como dos alumnos son iguales si sus DNIs concuerdan, y muchas analogas similares). En este caso, deberamos sobreescribir el mtodo equals para que compare nicamente los ISBN, los que, al ser iguales, generarn una salida verdadera. De no ser as, la salida ser falsa. Siempre deberas sobreescribir el mtodo equals si el operador de identidad no es apropiado para tu clase. Y si sobreescribs equals, sobreescrib hashCode tambin. El valor devuelto por hashCode es un entero que mapea un objeto dentro de una categora en una hashTable (ya se ver el Java Collections Framework). Un objeto debe siempre producir el mismo cdigo de Hashing. Sin embargo, los objetos pueden compartir cdigos de Hashing (no son necesariamente nicos). Escribir una funcin de hashing correcta es fcil (siempre retornar el mismo cdigo para el mismo objeto). Escribir una funcin de hashing eficiente (una que provea una buena distribucin de los objetos dentro de las categoras) es dificultoso y est fuera del alcance de este apunte. As y todo, la funcin de hashing para algunas clases es relativamente obvia. Por ejemplo, un cdigo de hashing obvio para un objeto Integer es el valor entero que representa. El mtodo toString El mtodo toString de la clase Object devuelve una cadena representando un objeto. Pods usar toString junto con System.out.println para mostrar una representacin textual de un objeto, como por ejemplo, la instancia de un Libro: System.out.println(miLibro.toString()); el cual, esperemos, imprima algo til, como esto: 0201914670: The JFC Swing Tutorial: A Guide to Constructing GUIs, 2nd Edition Authors: Kathy Walrath, Mary Campione, Alison Huml, Sharon Zakhour La representacin en cadena para un objeto depende enteramente del objeto. El mtodo toString es muy til cuando se quitan errores. Deberas sobreescribir este mtodo en todas tus clases.
El mtodo getClass El mtodo getClass devuelve una representacin en tiempo de ejecucin de la clase de un objeto. El mtodo devuelve un objeto del tipo Class, al cual se le puede pedir informacin sobre la clase, como ser su nombre, su superclase, y la interfaz que implementa. No pods sobreescribir el mtodo getClass. Un ejemplo de invocacin sera el siguiente: miObjeto.getClass().getSimpleName();