¡ATENCIÓN QUE ESTO ES IMPORTANTE! Hemos visto que gracias a la herencia podemos escribir y reescribir un método para adaptarlo a nuestras necesidades en cada momento. Siguiendo una linea de concreción descendiente (poligono =⇒ rectangulo, triangulo, pentágono, etc =⇒ triangulo equilatero, triangulo isósceles, etc) y concretando los métodos cada vez mas. Y si… en vez de concretar los métodos cada vez mas lo que hacemos es declararlos y implementarlos, cada uno en su concreción.
Es decir… Y si declaramos una clase abstracta (valga la redundancia) que defina sólamente lo que hará un poligono, pero no como lo hará? Total, el cómo lo hará ya lo definiremos en las concreciones, para que definir y redefinir métodos inutilmente?
Cojamos el caso anterioro. Un polígono ¿Qué tiene que hacer? Pues bastante poco. Pintarse… y poco mas. Pos ala. la clase abstracta Polígono tendrá el método pintarse y ya está. ¿Pero como se pinta un polígono? pues yo que se! Yo sé que se pinta pero…. A ver, tu…. ¿Cómo se pinta un polígono? la respuesta correcta es la siguiente pregunta ….¿Qué polígono quieres que pinte? Para saber cómo hacerlo necesito saber cual. Pues… no se… pinta un triangulo. Ahh.. vale ahora se como hacerlo.
¡Exacto! Eso mismo es. Exactamente igual que tu tienes ideas abstractas van adquiriendo grados de concreción hasta materializarse en objetos. ¡Que orijinales! Y para decir que un método o clase es abstracto que palabra clave usan? abstract claro!
ahi tienes otro ejemplo para que lo veas:
//AbstractaMusical.java
// ejemplo de comportamiento de clases abstractas
import java.util.*;
abstract class Instrumento{
int i; // almacenamiento reservado a cada instancia
public abstract void tocar();
public String que(){
return "Instrumento";
}
public abstract void afinar();
}
//------------------------------------------------------------------
class Viento extends Instrumento {
public void tocar(){
System.out.println("viento.tocando()");
}
public String que(){
return "viento";
}
public void afinar(){}
}
//------------------------------------------------------------------
class Percusion extends Instrumento {
public void tocar(){
System.out.println("percusion.tocando()");
}
public String que(){
return "percusion";
}
public void afinar(){}
}
//------------------------------------------------------------------
class Cuerda extends Instrumento {
public void tocar(){
System.out.println("cuerda.tocando()");
}
public String que(){
return "cuerda";
}
public void afinar(){}
}
//------------------------------------------------------------------
class MaderaViento extends Viento {
public void tocar(){
System.out.println("maderaviento.tocando()");
}
public String que(){
return "maderaviento";
}
public void afinar(){}
}
//------------------------------------------------------------------
class Metal extends Viento {
public void tocar(){
System.out.println("metal.tocando()");
}
public String que(){
return "metal";
}
public void afinar(){System.out.println("metal.afinando()");}
}
//------------------------------------------------------------------
public class AbstractaMusical{
static void afinar(Instrumento i){
i.tocar();
}
static void afinarTodo(Instrumento[] e){ // nota que le paso un array de instrumentos
for(int i=0; i<e.length; i++){
afinar(e[i]);
}
}
public static void main(String[] args){
Instrumento[] orquesta = new Instrumento[5];
int i=0;
orquesta[i++]= new Viento();
orquesta[i++]= new Percusion();
orquesta[i++]= new Cuerda();
orquesta[i++]= new MaderaViento();
orquesta[i++]= new Metal();
afinarTodo(orquesta);
}
}
Pero eso no es todo amigos, aun hay mas! Siendo un poco inteligentes y combinando herencia y composición podemos hacer cosas tan versátiles como esta:
//Transformar.java
// diseño con herencia y composicion
// mucho mas eficiente
abstract class Actor{
abstract void actuar();
}
//------------------------------------------------------------
class ActorFeliz extends Actor{
public void actuar(){
System.out.println("Actor Feliz ()");
}
}
//------------------------------------------------------------
class ActorTriste extends Actor{
public void actuar(){
System.out.println("Actor Triste ()");
}
}
//------------------------------------------------------------
class Escenario{
Actor a = new ActorFeliz();
void cambiar(){ a = new ActorTriste(); }
void ir(){ a.actuar();}
}
//------------------------------------------------------------
public class Transformar{
public static void main(String[] args){
Escenario s = new Escenario();
s.ir();
s.cambiar();
s.ir();
}
}