Unificar código en clase abstracta

Iniciado por CaTZ, 14 Enero 2015, 16:04 PM

0 Miembros y 2 Visitantes están viendo este tema.

CaTZ

Buenas tardes,

Tengo un problemilla con un tema y creo que es porque no tengo claro algunos conceptos.

Lo que tengo que hacer es unificar el código idéntico de 2 clases en otra clase abstracta para evitar duplicar el código.

Suponiendo que en Class1 y en Class2 hay 2 métodos (Metodo1 y Metodo2) que comparten código, sería meter ese código en una tercera clase abstracta (AbstractClass) para unificar el código y así cuando haya que modificar algo sólo se modifique en un sitio. El problema que tengo es que no se cómo tengo que llamar a los métodos de la clase abstracta desde las otras clases ya que yo tenía entendido que en la clase abstracta sólo se ponía el método (sin implementar código) y desde cada clase se controlaba el comportamiento.

Pues bien...yo he pensado en esto (de forma resumida):

AbstractClass
public abstract class AbstractClass{
              public boolean Metodo1 {
                    bla bla bla bla......
                    return true;
              }
              public boolean Metodo2 {
                    bla bla bla bla......
                    return false;
              }
}


Class1
public class Class1 extends AbstractClass{
              public boolean Metodo1();
              public boolean Metodo2();
}


Class2
public  Class2 extends AbstractClass{
              public boolean Metodo1();
              public boolean Metodo2();
}


¿Cómo debería hacerlo?

Muchas gracias de antemano!

iGust4v0x

#1
Se supone que si extiendes 2 clases de una sola, es porque ambas clases necesitan de los métodos y/o propiedades de la clase padre (sea abstracta o no). Además, puedes sobreescribir dichos métodos para aplicar polimorfismo.

Antes que nada un ejemplo:

Código (java) [Seleccionar]
public interface Animal {

   String name();
   void setName(String name);
   void doSomething();
   String description();
}


Código (java) [Seleccionar]
public abstract class AnimalImpl implements Animal {
   
   private String name;
   
   public AnimalImpl(String name) {
       this.name = name;
   }

   @Override
   public String getName() {
       return name;
   }
   
   @Override
   public void setName(String name) {
       this.name = name;
   }
   
   @Override
   public void doSomething();
   
   @Override
   public String description();
   
}


Código (java) [Seleccionar]
public class Dog extends AnimalImpl {
   
   public Dog(String name) {
       super(name);
   }

   @Override
   public void doSomething() {
       System.out.println("Guarf Guarf Guarf!");
   }
   
   @Override
   public String description() {
       return "perro";
   }
   
}


Código (java) [Seleccionar]
public class Cat extends AnimalImpl {
   
   public Cat(String name) {
       super(name);
   }

   @Override
   public void doSomething() {
       System.out.println("Miau maiu miaauuu");
   }
   
   @Override
   public String description() {
       return "gato";
   }
   
}


Código (java) [Seleccionar]
public class Owner {
   
   String name;
   Animal pet;
   
   public Owner() {}
   
   public Owner(String name, Animal pet) {
       this.name = name;
       this.pet = pet;
   }
   
   public String getName() {
       return name;
   }
   
   public void setName(String name) {
       this.name = name;
   }
   
   public Animal getPet() {
       return pet;
   }
   
   public void setPet(Animal pet) {
       this.pet = pet;
   }
   
   @Override
   public String toString() {
       return "Hola, mi nombre es "+name+", mi mascota se llama "+pet.getName()+" y es un "+pet.getDescription()+
       ".\n"+pet.doSomething();
   }
}


Código (java) [Seleccionar]
public class Main {
   public static void main(String[] args) {
       Animal bobby = new Dog("Bobby");
       Animal minina = new Cat("Minina");
       
       Owner guillermo = new Owner("Guillermo", bobby);
       Owner vilma = new Owner("Vilma", minina);
       
       System.out.println(guillermo); // la llamada a toString() es implícita
       System.out.println(vilma);
   }
}


Citar
Output:
Hola, mi nombre es Guillermo, mi mascota se llama Bobby y es un perro.
Guarf Guarf Guarf!

Hola, mi nombre es Vilma, mi mascota se llama Minina y es un gato.
Miau miau miaauuu

Respecto a tu pregunta, si ambos comparten código, el código compartido debería estar en la clase padre. Recuerda, que en una clase abstracta, a diferencia de las interfaces, sí se pueden implementar métodos.


Saludos.

JonaLamper

#2
Sería más o menos así:

Clase MiClaseAbstracta (clase padre con dos métodos abstractos):
Código (java) [Seleccionar]
public abstract class MiClaseAbstracta {
  public abstract int Metodo1 ();
  public abstract int Metodo2 ();
}


Clase MiClase1 (clase hijo que debe implementar los dos métodos abstractos de la clase padre):
Código (java) [Seleccionar]
public class MiClase1 extends MiClaseAbstracta {
  public int Metodo1 () {
     return this.numero1;
  }
  public int Metodo2 () {
     return this.numero2;  
 }

}


Clase MiClase2 (clase hijo que debe implementar los dos métodos abstractos de la clase padre):
Código (java) [Seleccionar]
public class MiClase2 extends MiClaseAbstracta {
  public int Metodo1 () {
     return this.numero3;
  }
  public int Metodo2 () {
     return this.numero4;  
  }
}




La jerarquía es esta:

                                                         MiClaseAbstracta
                                                                    |      
                                                                    |
                                                           _____ | _____
                                                           |                  |      
                                                           |                  |      
                                                    MiClase1        MiClase2

         
Es decir, digamos que en tu clase abstracta (que actúa como padre) te declaras los métodos abstractos. Y las subclases que estén por debajo, deben implementar dichos métodos (es obligatorio que implementen todos los métodos abstractos de la clase padre). Además de esto, la clase padre también puede tener sus propios métodos implementados (a los cuales las clases hijos podrán tener acceso).
Utilizar palabras para hablar de palabras es como utilizar un lápiz para hacer un dibujo de ese lápiz sobre el mismo lápiz.

CaTZ

Muchas gracias a los 2 por vuestras respuestas.

Yo había pensado hacer lo de JonaLamper pero es que en mi caso el Metodo1 y el Metodo2 son exactamente iguales para la Clase1 y Clase2, por eso tengo que implementar ambos métodos en la clase padre (ClaseAbstracta), pero el caso es:

¿Cómo llamo al método desde la clase hija?¿Simplemente poniendo el nombre?

Mi clase abstracta sería esta:

public abstract class MiClaseAbstracta {
     public void Metodo1 () {
         return this.numero1;
     }

     public void Metodo2 () {
         return this.numero2;
     }
}


Y por ejemplo mi Clase1 sería:

public class MiClase1 extends MiClaseAbstracta {
     //¿Aquí como llamo al Metodo1 y Metodo2?
}


Muchas gracias!

JonaLamper

#4
Se llaman exactamente igual que si estuvieran en la Clase1 o la Clase2.

Cuando hay herencia, los métodos y atributos de la clase padre se heredan a todos sus hijos (como si dichos métodos estuvieran declarados en los hijos).

Luego también depende de la visibilidad que tengas en esos métodos o atributos (public, protected o private), pero si son públicos no hay problema.

Una posible llamada sería esta:


Código (java) [Seleccionar]
public class MiClase1 extends MiClaseAbstracta {
    //Supongamos que en MiClase1 tengo un atributo que quiero que tome el valor que me devuelve el Metodo1 (que es de tipo int)
     private int MiNumero;

     this.MiNumero = Metodo1();
}




Nota: hay una cosa que está mal (aunque directamente no influya en entender este concepto). Para poner el ejemplo te he puesto que los métodos eran de tipo void, y los métodos de tipo void no devuelven ningún valor. Así que imagina que en vez de ser tipo void son de tipo int (es decir, me devuelven un valor de tipo int). Te lo he cambiado en el ejemplo de arriba.
Utilizar palabras para hablar de palabras es como utilizar un lápiz para hacer un dibujo de ese lápiz sobre el mismo lápiz.

CaTZ

Buenas JonaLamper,

No se por qué pero de esa forma no me sale el método de la clase padre. ¿Sería lo mismo esto?

...
....
this.MiNumero = super.Metodo1();


JonaLamper

Disculpa, el atributo debería estar en la clase padre  :P
Utilizar palabras para hablar de palabras es como utilizar un lápiz para hacer un dibujo de ese lápiz sobre el mismo lápiz.

CaTZ

Perfecto esto ya lo tengo, gracias!

Ahora si no es mucha molestia tengo otra dudilla....

Si tengo un parámetro en la clase hija con un valor x, ¿Habría alguna manera de que la clase padre recogiera este parámetro?

JonaLamper

Utilizar palabras para hablar de palabras es como utilizar un lápiz para hacer un dibujo de ese lápiz sobre el mismo lápiz.

CaTZ

Disculpa un atributo! se me fue! xD