G.Bordel >Docencia >TAP | Técnicas Actuales de Programación | (curso 2010-2011) | |||||||
|
|||||||||
tema_anterior | Tema 4: Elementos relacionados con la orientación a objeto | tema_siguiente |
4.3- Herencia
Palabras reservadas en Java | |||||
abstract | boolean | break | byte | case | catch |
char | class | const* | continue | default | do |
double | else | extends | final | finally | float |
for | goto* | if | implements | import | instanceof |
int | interface | long | native | new | package |
private | protected | public | return | short | static |
strictfp** | super | switch | synchronized | this | throw |
throws | transient | try | void | volatile | while |
La herencia es un mecanismo que permite establecer una cierta relación entre clases que resulta de utilidad en dos sentidos: por un lado permite estructurar el conjunto de las clases dándole una cierta consistencia, y por otro permite un ahorro de esfuerzo de definición.
Visto desde el segundo punto de utilidad indicado, el hecho de que una clase A herede de
otra B significa que en su definición se incluye automáticamente
toda la definición de B sin necesidad de reescribirla. Para ello basta con utilizar en la declaración,
tras el nombre de la clase, la palabra clave "extends"
y el nombre de la clase B. Por
tanto toda la definición de clase que se realice en A, se irá añadiendo a la ya realizada automáticamente.
Los campos y métodos de A serán todos los de B mas los que se incluyan específicamente en su definición.
Visto desde el primer punto de utilidad indicado, el hecho de que una clase A herede de
otra B significa que los objetos de esta clase A son objetos de un tipo específico dentro de
los que define la clase B. Es decir todos los objetos definidos por la clase A pueden ser considerados
como objetos de clase B, pero no al contrario. Para aclarar esto podemos concretar mediante un ejemplo:
una clase "CuentaCorriente"
puede heredar de otra denominada "CuentaBancaria"
una serie de campos
(como "saldo"
,etc) y de métodos (como "realizarMovimiento(*)"
, etc) añadiendo
otros específicos (como bloquearCantidad(*)
, etc). Un objeto de clase "CuentaCorriente"
puede considerarse tambien como de tipo "CuentaBancaria"
ya que posee todas sus características,
mientras que lo contrario no será necesariamente cierto. Pueden definirse otras clases que hereden de
"CuentaBancaria"
(como p.ej "CuentaDeAhorro"
) y que sean sub-clases distintas de
la "CuentaCorriente"
.
![]() Declaración de la clase CuentaCorriente como heredera de CuentaBancaria .
En el gráfico se muestra esta relación de herencia y otra similar con la clase CuentaDeAhorro
|
Esta estructuración del conjunto de las clases en función de la herencia es un árbol, es decir, existe una clase
"raiz" de la que parten una serie de ramas hacia sus clases herederas, que son a su vez raices de sub-arboles.
Cada clase, con excepción de la raiz, tienen una y solo una clase "padre".
En genral no resultará trivial el establecimiento de la herencia entre clases, ya que un determinado objeto puede
presentar caracteristicas de mas de una clase (p.ej, "pájaro" puede heredar de "animal" al compartir características
con el resto de animales, pero tambien puede heredar de "volador" al compartir características aplicables tanto a
animales como a aparatos con capacidad para volar). Esto se resolvería permitiendo la herencia múltiple, como hacen
otros lenguajes orientados a objetos (p.ej C++), pero en el planteamiento de Java se tuvo en cuenta que esta característica
tiene más desventajas que beneficios y se optó por no admitirla. Las capacidades de la herencia múltiple se obtienen
en Java mediante el mecanismo de los interfaces
que se estudiará más adelante.
La clase raiz en Java se denomina Object
, y se estudiará con detenimiento en un próximo capítulo. Como quiera
que Object
es la clase raiz de toda la estructura, quiere esto decir que el hecho de no explicitar
una herencia en la definición de una clase (no poner "extends <clase>"
) no quiere decir que la clase
este fuera de las relaciones de herencia, sino que tiene la herencia que podemos llamar "mínima" y su clase padre es
directamente la clase Object
.
Volviendo al aspecto "mecánico" de la herencia, decíamos que una clase A que heredaba de B podía definir nuevos elementos
a los ya adquiridos automáticamente. Hay que concretar aquí que tambien es posible que las definiciones específicas
coincidan en cierto modo con las heredadas, y en tal caso se hablará de una redefinición de la característica, es decir
se "anula" la característica heredada que se ve sustituida por la nueva definición. Es lo que en la terminología de la
orientación a objeto se denomina "sobreescritura". Esto permite que no sólo se añadan
características particulares a la nueva clase, sino que se particularicen características generales que pertenecian a la
clase padre. Pongamos un ejemplo: volviendo a las cuentas bancarias, podemos tener un método reintegro(*)
en la clase CuentaBancaria
que heredarán todas sus subclases, pero dependiendo del tipo de cuenta, la
política de reintegros puede ser distinta (p.ej. permitiendo o no descubiertos en la cuenta), de modo que si cada subclase
define de nuevo el método de un modo específico, se sustituye al heredado. Un método se considera reescrito cuando
coinciden el nombre, tipo de retorno y parámetros; otras características pueden variar pero, una vez más, tenemos que dejar
pendiente para más adelante el estudio de estos detalles.
Siguiente punto: 4.4- Encapsulamiento (ámbitos de accesibilidad)
Plataforma de soporte a curso y contenidos (c) German Bordel 2005. |