Hay muchas formas de hacerlo, asumiendo que por breed
quiere decir "crear hijos de mi parte".
Reflexión
primera es utilizar la reflexión. Si usted tiene un constructor sin argumentos para sus clases, esto es tan fácil como llamar Class.newInstance:
public Animal breed() {
try {
return (Animal) getClass().newInstance();
} catch (Exception ex) {
// TODO Log me
return null;
}
}
Si usted no tiene un constructor sin argumentos en todas sus subclases, usted tiene que tener una constructor uniforme en todas sus subclases. Por ejemplo, si usted tiene Cat(int, String)
y Dog(int, String)
, entonces usted necesita para obtener el constructor a través de Class.getConstructor
e invocar newInstance
en que:
return (Animal) getClass().getConstructor(int.class, String.class).newInstance(0, "Unnamed");
int
y String
aquí puede ser la edad y el nombre, por ejemplo. Así es como haces esto con reflexión.
Proveedores
Otra forma es utilizar esta interfaz sencilla:
public interface Provider<T> {
T create();
}
Después haga que su clase abstracta tomar un ejemplo de esto en su constructor:
public abstract class Animal {
private final Provider<Animal> animalProvider;
protected Animal(... , Provider<Animal> animalProvider) {
// ...
this.animalProvider = animalProvider;
}
public Animal breed() {
return animalProvider.create();
}
}
Luego, su las subclases pasarán un Provider<Animal>
a la superclase que creará nuevas instancias de la subclase:
public class Dog extends Animal {
public Dog(...) {
super(... , new DogProvider());
// ...
}
private static class DogProvider implements Provider<Animal> {
public Animal create() {
return new Dog(...);
}
}
}
Haz lo mismo para otras subclases.
Nota: si por breed
quiere decir "obtener el tipo de mí", entonces debe editar su pregunta para decirlo. Si esto es lo que quería decir, entonces esta es una solución viable:
public abstract class Animal {
protected final Breed breed;
protected Animal(... , Breed breed) {
// ...
this.breed = breed;
}
public Breed getBreed() {
return breed;
}
}
Recomiendo seguir las get
/set
convenciones para los métodos de contenedores de datos. Java tiene clases de beans diseñadas para manejar estas convenciones de nomenclatura, y es más o menos un estándar en muchas plataformas. Para sus subclases:
public class Dog extends Animal {
public Dog(...) {
super(... , new Breed(...));
// ...
}
}
sí, no es necesario que todos los métodos en una clase tienen que ser abstracta –
@SashiKant Aunque es verdad, no creo que eso es lo que el PO estaba pidiendo ... –