La
reutilización de código se refiere al comportamiento y a las técnicas que
garantizan que una parte o la totalidad de un programa informático
existente se pueda emplear en la construcción de otro programa. De esta forma se
aprovecha el trabajo anterior, se economiza tiempo, y se reduce la
redundancia.
La
manera más fácil de reutilizar código es copiarlo total o parcialmente desde el
programa antiguo al programa en desarrollo. Pero es trabajoso mantener múltiples
copias del mismo código, por lo que en general se elimina la redundancia dejando
el código reusable en un único lugar, y llamándolo desde los diferentes
programas. Este proceso se conoce como abstracción. La
abstracción puede verse claramente en las bibliotecas de software, en las
que se agrupan varias operaciones comunes a cierto dominio para facilitar el
desarrollo de programas nuevos. Hay bibliotecas para convertir información entre
diferentes formatos conocidos, acceder a dispositivos de almacenamiento
externos, proporcionar una interfaz con otros programas, manipular información
de manera conocida (como números, fechas, o cadenas de texto).
Para que
el código existente se pueda reutilizar, debe definir alguna forma de
comunicación o interfaz. Esto se puede dar por llamadas a una subrutina, a un
objeto, o a una clase.
Como se ha
comentado anteriormente la clase descendiente puede añadir sus propios atributos
y métodos pero también 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 técnica no es
recomendable.
2. Se puede
declarar un nuevo método de instancia con la misma cabecera que el de la
clase ascendiente, lo que supone su sobreescritura. Por lo tanto, la
sobreescritura o redefinición consiste en que métodos adicionales declarados en
la clase descendiente con el mismo nombre, tipo de dato devuelto y número y tipo
de parámetros sustituyen a los heredados.
3. Se puede
declarar un nuevo método de clase con la misma cabecera que el de la
clase ascendiente, lo que hace que éste quede oculto. Por lo tanto, los
métodos de clase o estáticos (declarados como static) no pueden ser
redefinidos.
4. Un método
declarado con el modificador final 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 implícita o de mediante la palabra reservada super.
6. En general
puede accederse a los métodos de la clase ascendiente que han sido redefinidos
empleando la palabra reservada super delante del identificador del método. Este
mecanismo sólo permite acceder al metodo perteneciente a la clase en el nivel
inmediatamente superior de la jerarquía de clases.
Construyamos la clase
Taxista.java con el siguiente código:
public class Taxista extends
Persona {
private int nLicencia;
public void setNLicencia(int
num){
nLicencia = num;
}
public int getLicencia(){
return nLicencia;
}
}
Y
construyamos ArranqueTaxista.java:
public class ArranqueTaxista {
public static void main (String arg[]){
Taxista
tax1 = new Taxista();
tax1.setNombre("Luis");
tax1.setEdad(50);
System.out.println( tax1.getNombre());
System.out.println(tax1.getEdad());
}
}
Ahora
intentemos usar el constructor que existía en la clase Persona que recibia el
nombre de la persona y vamos a usarlo para la clase Taxista. Para ello
construyamos la clase ArranqueTaxista2.java:
public class
ArranqueTaxista2 {
public static void main (String arg[]){
Taxista
tax1 = new Taxista("Jose");
tax1.setEdad(50);
System.out.println( tax1.getNombre());
System.out.println(tax1.getEdad());
System.out.println(tax1.getNLicencia());
}
}
Se
genera un error de compilación, debido a que los constructores no se heredan,
sino que hay que definir nuestros propios constructores. Agreguemos en la clase
Taxista los siguientes constructores:
public
Taxista(int licencia){
super();
nLicencia = licencia;
}
public
Taxista(String nombre,int licencia){
super(nombre);
nLicencia = licencia;
}
Ahora si
podremos compilar y ejecutar la clase ArranqueTaxista2. La llamada al método
super indica que estamos llamando a un constructor de la clase base (pensemos
que un Taxista antes que Taxista es Persona y por tanto tiene sentido llamar al
constructor de Persona antes que al de Taxista). Además gracias al número de
parámetros de la llamada a super podemos especificar cuál de los constructores
de la clase base queremos llamar.
En java
se pueden emplear dos palabras clave: this y super. Como vimos en la unidad 1,
this hace alusión a todo el objeto y super hace alusión a la parte heredada, por
ello empleamos super para referenciar al constructor de la clase
base.
Ahora
vamos a agregar la función getNombre dentro de la clase Taxista, es decir,
tenemos la misma función en Persona y en Taxista:
public
String getNombre() {
return
"Soy un taxista y me llamo: " + super.getNombre();
}
Compilamos Taxista y ejecutamos ArranqueTaxista2. Veremos que el mensaje
que aparece en pantalla demuestra que la función getNombre llamada es la de del
tipo real del objeto construido, en este caso la de la clase derivada que es
Taxista.
Tambien
apreciamos que para acceder al atributo nombre es necesario acceder al método
getNombre de la clase base (y por ello emplear super).
En java
los atributos y métodos de la clase base pueden cambiar su modificador de
visibilidad dentro de la clase derivada, la siguiente tabla recoge dichos
cambios:
Modificadores en la clase base:
public
private
protected
paquete
En la
clase derivada se transforman en:
public
inaccesible
protected
paquete
Inaccesible significa que, a pesar de haber sido heredado, no hay
permisos en la clase derivada para poder acceder a dicho elemento inaccesible,
pero aún así, se pueden llamar a métodos de la clase base que si pueden acceder
y modificar al elemento.
Recordemos que protected significa que es private, pero que al heredar
no se hace inaccesible, es decir que desde la clase derivada se puede
acceder.
No hay comentarios:
Publicar un comentario