Está en la página 1de 9

168 A. Garca-Beltrn y J .M.

Arranz


16. Herencia

Objetivos:
a) Definir el concepto de herencia entre clases
b) Interpretar el cdigo fuente de una aplicacin Java donde aparecen clases
relacionadas mediante la herencia
c) Construir una aplicacin Java sencilla, convenientemente especificada, que haga
uso de la herencia entre clases

16.1. Definicin de herencia
La herencia es una propiedad que permite la declaracin de nuevas clases a partir de otras ya
existentes. Esto proporciona una de las ventajas principales de la Programacin Orientada a Objetos:
la reutilizacin de cdigo previamente desarrollado ya que permite a una clase ms especfica
incorporar la estructura y comportamiento de una clase ms general.

Cuando una clase B se construye a partir de otra A mediante la herencia, la clase B hereda
todos los atributos, mtodos y clases internas de la clase A. Adems la clase B puede redefinir los
componentes heredados y aadir atributos, mtodos y clases internas especficas.

Para indicar que la clase B (clase descendiente, derivada, hija o subclase) hereda de la clase
A (clase ascendiente, heredada, padre, base o superclase) se emplea la palabra reservada extends
en la cabecera de la declaracin de la clase descendiente. La sintaxis es la siguiente:

publ i c cl ass ClaseB extends ClaseA {
/ / Decl ar aci on de at r i but os y met odos especi f i cos de Cl aseB
/ / y/ o r edecl ar aci on de component es her edados
}

Por ejemplo, a partir de la clase Pr eci o:

/ **
* Ej empl o de decl ar aci on de l a cl ase Pr eci o
* A. Gar ci a- Bel t r an - novi embr e, 2005
*/
publ i c cl ass Precio {
/ / Var i abl e de i nst anci a
publ i c doubl e eur os;
/ / Met odos publ i cos
publ i c doubl e da( ) {
r et ur n eur os;
}
publ i c voi d pone( doubl e x) {
eur os=x;
}
}

se construye la clase Pr oduct o como descendiente de la clase Pr eci o de la siguiente forma:

/ **
* Ej empl o de decl ar aci on de l a cl ase Pr oduct o
* cl ase pr oduct o desci ende de Pr eci o
Programacin orientada a objetos con J ava 169


* A. Gar ci a- Bel t r an - di ci embr e, 2005
*/

publ i c cl ass Producto extends Pr eci o {
/ / Var i abl e de i nst anci a
publ i c i nt codi go;
/ / Met odos publ i cos
publ i c i nt daCodi go( ) {
r et ur n codi go;
}
publ i c voi d asi gnaCodi go( i nt x) {
codi go=x;
}
publ i c voi d asi gnaPr oduct o( i nt cod, doubl e p) {
asi gnaCodi go( cod) ;
pone( p) ;
}
publ i c St r i ng t oSt r i ng( ) {
r et ur n "Codi go: " + codi go + " ; pr eci o: " + eur os + " eur os";
}
}

La clase Pr uebaCl asePr oduct o trabaja con dos instancias de la clase Pr oduct o:

/ **
* Demost r aci on de l a cl ase Pr oduct o
* A. Gar ci a- Bel t r an - di ci embr e, 2005
*/
publ i c cl ass PruebaClaseProducto {
publ i c st at i c voi d mai n ( St r i ng [ ] ar gs) {
Producto p = new Producto( ) ;
p. asi gnaPr oduct o( 200201, 15. 8) ;
Syst em. out . pr i nt l n( p. t oSt r i ng( ) ) ;
Producto q = new Producto( ) ;
q. asi gnaCodi go( 200202) ;
q. pone( 34. 3) ;
Syst em. out . pr i nt l n( q. t oSt r i ng( ) ) ;
}
}

Durante la ejecucin del cdigo anterior, se generan las instancias (Figura 16.1),
referenciadas por p y q, cada una de las cuales est compuesta por dos atributos: eur os, variable
de instancia heredada de la clase Pr eci o y codi go, variable de instancia especfica de la clase
Pr oduct o.


Figura 16.1. Representacin grafica de las instancias de la clase Pr oduct o.

Por otro lado, la ejecucin de Pr uebaCl asePr oduct o produce la siguiente salida por
pantalla:

170 A. Garca-Beltrn y J .M. Arranz


$>j avac Pr uebaCl asePr oduct o. j ava

$>j ava Pr uebaCl asePr oduct o

Codi go: 200201 ; pr eci o: 15. 8 eur os
Codi go: 200202 ; pr eci o: 34. 3 eur os
16.2. Jerarqua de clases
Java permite mltiples niveles de herencia pero no la herencia multiple, es decir una clase
slo puede heredar directamente de una clase ascendiente. Por otro lado, una clase puede ser
ascendiente de tantas clases descendiente como se desee (un unico padre, multitud de hijos). En la
Figura 16.2 se muestra grficamente un ejemplo de jerarqua entre diferentes clases relacionadas
mediante la herencia.


Figura 16.2. Representacin de una jerarqua de clases relacionadas mediante la herencia

16.3. Redefinicin de elementos heredados

Como se ha comentado anteriormente la clase descendiente puede aadir sus propios
atributos y mtodos pero tambin puede sustituir u ocultar los heredados. En concreto:
1. Se puede declarar un nuevo atributo con el mismo identificador que uno heredado,
quedando este atributo oculto. Esta tcnica no es recomendable.
2. Se puede declarar un nuevo mtodo de instancia con la misma cabecera que el de la clase
ascendiente, lo que supone su sobreescritura. Por lo tanto, la sobreescritura o redefinicin
consiste en que mtodos adicionales declarados en la clase descendiente con el mismo
nombre, tipo de dato devuelto y nmero y tipo de parmetros sustituyen a los heredados.
Programacin orientada a objetos con J ava 171


3. Se puede declarar un nuevo mtodo de clase con la misma cabecera que el de la clase
ascendiente, lo que hace que ste quede oculto. Por lo tanto, los mtodos de clase o estticos
(declarados como st at i c) no pueden ser redefinidos.
4. Un mtodo declarado con el modificador f i nal tampoco puede ser redefinido por una clase
derivada.
5. Se puede declarar un constructor de la subclase que llame al de la superclase de forma
implcita o de mediante la palabra reservada super .
6. En general puede accederse a los mtodos de la clase ascendiente que han sido redefinidos
empleando la palabra reservada super delante del identificador del mtodo. Este mecanismo
slo permite acceder al metodo perteneciente a la clase en el nivel inmediatamente superior
de la jerarqua de clases.

16.4. La clase Object
Independientemente de utilizar la palabra reservada ext ends en su declaracin, todas las
clases derivan de una superclase llamada Obj ect . sta es la clase raz de toda la jerarqua de clases
de Java (Figura 16.3). El hecho de que todas las clases deriven implcitamente de la clase Obj ect
no se considera herencia mltiple.


Figura 16.3. J erarqua de clases predefinidas en J ava

Como consecuencia de ello, todas las clases tienen algunos mtodos heredados de la clase
Obj ect (Tabla 16.1).
Tabla 16.1. Algunos de los mtodos de la clase predefinida Obj ect
Mtodo Funcin
cl one( )
Genera una instancia a partir de otra de la misma clase.
equal s( )
Devuelve un valor lgico que indica si dos instancias de la misma clase son iguales.
t oSt r i ng( )
Devuelve un St r i ng que contiene una representacin como cadena de caracteres
de una instancia.
f i nal i ze( )
Finaliza una instancia durante el proceso de recogida de basura (se ver ms
adelante).
172 A. Garca-Beltrn y J .M. Arranz


hashCode( )
Devuelve una clave hash (su direccin de memoria) para la instancia
get Cl ass( )
Devuelve la clase a la que pertenece una instancia.


Es bastante frecuente tener que sobreescribir algunos de estos mtodos. Por ejemplo, para
verificar si dos instancias son iguales en el sentido de contener la misma informacin en sus atributos
se debera sobreescribir el mtodo equal s( ) . El siguiente cdigo muestra un ejemplo de
mdificacin de la clase Pr oduct o para incluir una sobreescritura del mtodo equal s( ) :

publ i c cl ass Pr oduct o ext ends Pr eci o {
. . .
publ i c bool ean equal s( Obj ect a) {
i f ( a i nst anceof Pr oduct o)
r et ur n ( codi go==a. daCodi go( ) ) ;
el se
r et ur n f al se;
}
}

Tambin es bastante habitual sobreescribir el mtodo t oSt r i ng( ) .
16.5. Herencia y constructores
La subclase necesita normalmente que se ejecute el constructor de la superclase antes que su
propio constructor para inicializar las variables de instancia heredadas. La solucin consiste en
utilizar la palabra reservada super seguida entre parntesis de los parmetros correspondiente en el
cuerpo del constructor de la subclase. Es decir, incluir la siguiente sentencia como primera lnea de
cdigo:

super( argumentos opcionales) ;

De esta forma la implementacin de un constructor de la clase descendiente slo necesita
inicializar directamente las variables de instancia no heredadas. Si no aparece como primera
sentencia, el compilador inserta una llamada implcita super ( ) ; que inicializa las variables de
instancia a cero, f al se, carcter nulo o nul l dependiendo de su tipo. Esta llamada en cadena a los
constructores de las clases ascendientes llega hasta el origen de la jerarqua de clases, es decir, hasta
el constructor de la clase Obj ect . En cualquier caso, la creacin de una nueva instancia mediante
un constructor debe tener tres fases:

1. Llamada al constructor de la clase ascendiente
2. Se asignan valores a los atributos
3. Se ejecuta el resto del constructor

16.6. Casting o moldes entre objetos con relacin de herencia

El casting o moldeo permite el uso de un objeto de una clase en lugar de otro de otras clase
con el que haya una relacin de herencia. Por ejemplo:

Obj ect a = new Pr oduct o( ) ;

Programacin orientada a objetos con J ava 173


Entonces a es momentneamente tanto una instancia de la clase Obj ect como Pr oduct o
(hasta que ms adelante se le asigne un objeto que no sea un Pr oduct o). A esto se le llama moldeo
implcito.

Por otro lado, si se escribe:

Pr oduct o b = a;

se obtendr un error de compilacin porque el objeto referenciado por a no es considerado por el
compilador como un Pr oduct o. Sin embargo se le puede indicar al compilador que a la referencia
a se le va a asignar obligatoriamente un Pr oduct o.

Pr oduct o b = ( Pr oduct o) a;

Este moldeo explcito introduce la verificacin durante la ejecucin de que a la referencia a se
le ha asignado un Pr oduct o as que el compilador no genera un error. En el caso que durante la
ejecucin la referencia a no fuera a un Pr oduct o, se generara una excepcin. Para asegurar esta
situacin y evitar el error de ejecucin se podra emplear el operador i nst anceof :

i f ( a i nst anceof Pr oduct o) {
Pr oduct o b = ( Pr oduct o) a;
}

16.7. Clases y mtodos abstractos
Una clase abstracta es una clase de la que no se pueden crear instancias. Su utilidad consiste
en permitir que otras clases deriven de ella. De esta forma, proporciona un modelo de referencia a
seguir a la vez que una serie de mtodos de utilidad general. Las clases abstractas se declaran
empleando la palabra reservada abst r act como se muestra a continuacin:

publ i c abstract cl ass IdClase . . .

Una clase abstracta puede componerse de varios atributos y mtodos pero debe tener, al
menos, un mtodo abstracto (declarado tambin con la palabra reservada abst r act en la
cabecera). Los mtodos abstractos no se implementan en el cdigo de la clase abstracta pero las
clases descendientes de sta han de implementarlos o volver a declararlos como abstractos (en cuyo
caso la subclase tambin debe declararse como abstracta). En cualquier caso, ha de indicarse el tipo
de dato que devuelve y el nmero y tipo de parmetros. La sintaxis de declaracin de un mtodo
abstracto es:

abstract modificador tipo_retorno idClase( lista_parametros) ;

Si una clase tiene mtodos abstractos, entonces tambin la clase debe declararse como
abstracta. Como los mtodos de clase (st at i c) no pueden ser redefinidos, un mtodo abstracto no
puede ser esttico. Tampoco tiene sentido que declarar constructores abstractos ya que un
constructor se emplea siempre al crear una instancia (y con las clases abstractas no se crean
instancias).

Ejemplo de cdigo con la declaracin de clase abstracta:

174 A. Garca-Beltrn y J .M. Arranz


/ **
* Decl ar aci on de l a cl ase abst r act a Fi gur aGeomet r i ca
* A. Gar ci a- Bel t r an - novi embr e, 2005
*/
publ i c abstract cl ass FiguraGeometrica {
/ / Decl ar aci on de at r i but os
pr i vat e St r i ng nombr e;
/ / Decl ar aci on de met odos
abstract publ i c doubl e ar ea( ) ;
publ i c f i gur aGeomet r i ca ( St r i ng nombr eFi gur a ) {
nombr e = nombr eFi gur a;
}
f i nal publ i c bool ean mayor Que ( Fi gur aGeomet r i ca ot r a) {
r et ur n ar ea( ) >ot r a. ar ea( ) ;
}
f i nal publ i c St r i ng t oSt r i ng( ) {
r et ur n nombr e + " con ar ea " + ar ea( ) ;
}
}

Como ejemplo de utilizacin de una clase abstracta en el siguiente cdigo la clase
Rect angul o se construye a partir de la clase abstracta Fi gur aGeomet r i ca:

/ **
* Ej empl o de uso de l a decl ar aci on de una cl ase abst r act a
* Decl ar aci on de l a cl ase Rect angul o
* A. Gar ci a- Bel t r an - novi embr e, 2005
*/
publ i c cl ass Rectangulo ext ends FiguraGeometrica {
pr i vat e doubl e base;
pr i vat e doubl e al t ur a;
publ i c Rect angul o ( doubl e l ar go, doubl e ancho) {
super ( "Rect angul o") ;
base=l ar go;
al t ur a=ancho;
}
publ i c doubl e ar ea ( ) {
r et ur n base * al t ur a;
}
}

Ejemplo de uso de la clase Rect angul o:

/ **
* Ej empl o de uso de l a cl ase Rect angul o
* A. Gar ci a- Bel t r an - novi embr e, 2005
*/
publ i c cl ass pr uebaRect angul o {
publ i c st at i c voi d mai n ( St r i ng [ ] ar gs ) {
Rectangulo r 1;
r 1 = new Rect angul o( 12. 5, 23. 7) ;
Syst em. out . pr i nt l n( "Ar ea de r 1 = " + r 1. ar ea( ) ) ;
Rectangulo r 2 = new Rect angul o( 8. 6, 33. 1) ;
Syst em. out . pr i nt l n( "Ar ea de r 2 = " + r 2. t oSt r i ng( ) ) ;
i f ( r 1. mayor Que( r 2) )
Syst em. out . pr i nt l n( "El r ect angul o de mayor ar ea es r 1") ;
el se Syst em. out . pr i nt l n( "El r ect angul o de mayor ar ea es r 2") ;
}
}

Salida por pantalla de la ejecucin del cdigo anterior:
Programacin orientada a objetos con J ava 175



$>j ava Pr uebaRect angul o

Ar ea de r 1 = 296. 25
Ar ea de r 2 = Rect angul o con ar ea 284. 66
El r ect angul o de mayor ar ea es r 1
16.8. Clases y mtodos finales
Una clase declarada con la palabra reservada f i nal no puede tener clases descendientes.
Por ejemplo, la clase predefinida de Java Mat h est declarada como f i nal .

A modo de ejemplo, se desarrolla una clase final Mat hBi s (de operatividad similar a la
clase Mat h estndar de Java) que incluye la declaracin de dos mtodos que calculan y devuelven
respectivamente las siguientes funciones trigonomtricas:

1 ln ) ( senh
2 1

x x x


1 ln ) ( cosh
2 1

x x x

El cdigo fuente de la clase es:

/ **
* Ej empl o de decl ar aci on de una cl ase f i nal
* Decl ar aci on de l a cl ase Mat hBi s
* A. Gar ci a- Bel t r an - di ci embr e, 2004
*/
publ i c final cl ass MathBis {
publ i c st at i c doubl e asi nh( doubl e x) {
r et ur n Mat h. l og( x+Mat h. sqr t ( x*x+1) ) ;
}
publ i c st at i c doubl e acosh( doubl e x) {
r et ur n Mat h. l og( x+Mat h. sqr t ( x*x- 1) ) ;
}
}

Ejemplo de uso de la clase Mat hBi s:

/ **
* Ej empl o de uso de una cl ase f i nal
* Decl ar aci on de l a cl ase pr uebaMat hBi s
* A. Gar ci a- Bel t r an - di ci embr e, 2004
*/
publ i c cl ass PruebaMathBis {
publ i c st at i c voi d mai n ( St r i ng [ ] ar gs) {
f or ( i nt i =- 5; i <10; i ++) {
doubl e x = i / 5. 0;
Syst em. out . pr i nt ( "Par a x = " + x) ;
Syst em. out . pr i nt ( ": asi nh( x) = " +Mat hBi s. asi nh( x) ) ;
Syst em. out . pr i nt l n( ", acosh( x) = " +Mat hBi s. acosh( x) ) ;
}
}
}

Salida por pantalla de la ejecucin del cdigo anterior:
176 A. Garca-Beltrn y J .M. Arranz



$>j ava Pr uebaMat hBi s

Par a x = - 1. 0: asi nh( x) = - 0. 8813735870195428, acosh( x) = NaN
Par a x = - 0. 8: asi nh( x) = - 0. 7326682560454109, acosh( x) = NaN
Par a x = - 0. 6: asi nh( x) = - 0. 5688248987322477, acosh( x) = NaN
Par a x = - 0. 4: asi nh( x) = - 0. 39003531977071504, acosh( x) = NaN
Par a x = - 0. 2: asi nh( x) = - 0. 19869011034924128, acosh( x) = NaN
Par a x = 0. 0: asi nh( x) = 0. 0, acosh( x) = NaN
Par a x = 0. 2: asi nh( x) = 0. 19869011034924142, acosh( x) = NaN
Par a x = 0. 4: asi nh( x) = 0. 3900353197707155, acosh( x) = NaN
Par a x = 0. 6: asi nh( x) = 0. 5688248987322475, acosh( x) = NaN
Par a x = 0. 8: asi nh( x) = 0. 732668256045411, acosh( x) = NaN
Par a x = 1. 0: asi nh( x) = 0. 8813735870195429, acosh( x) = 0. 0
Par a x = 1. 2: asi nh( x) = 1. 015973134179692, acosh( x) = 0. 6223625037147785
Par a x = 1. 4: asi nh( x) = 1. 1379820462933672, acosh( x) = 0. 867014726490565
Par a x = 1. 6: asi nh( x) = 1. 2489833279048763, acosh( x) = 1. 0469679150031885
Par a x = 1. 8: asi nh( x) = 1. 3504407402749723, acosh( x) = 1. 1929107309930491


Por otro lado, un mtodo declarado como f i nal no puede ser redefinido por una clase
descendiente. Los mtodos que son llamados desde los constructores deberan declararse como
f i nal , ya que si un constructor llama a un mtodo que no lo sea, la subclase podra haberla
redefinido con resultados indeseables.

También podría gustarte