在Java抽象类中创建新对象
我有两个使用非常相似的方法的对象,除了一行。例如:在Java抽象类中创建新对象,java,abstract-class,Java,Abstract Class,我有两个使用非常相似的方法的对象,除了一行。例如: public class Cat extends Animal public class Dog extends Animal 它们都在抽象类Animal中使用breed方法。一个调用newdog(),另一个调用newcat()。现在我只是把它声明为abstract public void bride()
public class Cat extends Animal
public class Dog extends Animal
它们都在抽象类
Animal
中使用breed
方法。一个调用newdog()
,另一个调用newcat()
。现在我只是把它声明为abstract public void bride()但是有没有一种方法可以推广它,这样我就不必把它变成一个被重写的抽象方法?没有。你必须像下面那样做
我想你想在你的抽象课上
public abstract Breed getBreed();
然后在每个子类中
public Breed getBreed() {
return new DogBreed();
}
还有一只类似的猫
或
在动物类中有一块被称为繁殖的保护地。然后可以在每个子类中对其进行初始化。这将消除对抽象方法的需要。比如说
public abstract class Animal {
Breed breed;
...
}
然后在狗有
public class Dog extends Animal {
public Dog() {
breed = new DogBreed();
}
}
还有一些类似猫的东西
它可能值得您同时将品种传递给Dog/Cat ctor,以便您可以创建不同品种的狗对象,而不是将您的模型仅限于一个品种的狗
我不确定你的例子中的品种模型是否正确。你真的想让这只新狗成为一个品种吗?或者你是说打字?在这种情况下,它只是一个动物,而抽象的方法返回动物是一种方法。事实上,是的,你可以。您需要使用反射,这样性能可能会有点不确定,但这(未经测试)应该可以:
public abstract class Animal{
public Animal breed(){
return getClass().newInstance();
}
//other methods
}
这将返回一个实际调用类型的新实例,而不是动物类型(实现它的地方)
这实际上有点类似于。尽管在本例中,您创建的是一个新实例,而不是复制现有实例
编辑
正如@FrankPavageau在评论中指出的,您可以通过使用
public abstract class Animal{
public Animal breed(){
return getClass().getConstructor().newInstance();
}
//other methods
}
它将把抛出的任何异常封装在一个InvocationTargetException
中,该函数更干净,可能更容易调试。感谢@FrankPavageau的建议。有很多方法可以做到这一点,假设繁殖
的意思是“创造我的孩子”
反射
首先是使用反射。如果您的类有一个无参数构造函数,则调用以下命令即可:
如果没有在所有子类中都使用无参数构造函数,那么必须在所有子类中使用统一的构造函数。例如,如果您有Cat(int,String)
和Dog(int,String)
,那么您需要通过获取构造函数并调用它:
int
和String
这里可能是年龄和姓名。这就是如何通过反射来实现的
提供商
另一种方法是使用此简单界面:
public interface Provider<T> {
T create();
}
我建议遵循数据容器方法的get
/set
约定。Java设计了bean类来处理这些命名约定,它或多或少是许多平台的标准。对于您的子类:
public class Dog extends Animal {
public Dog( ... ) {
super( ... , new Breed( ... ));
// ...
}
}
是的,一个类中的所有方法都不需要abstract@SashiKant虽然是真的,但我不认为这是OP所要求的…尝试了这个,但它抛出了实例化异常@Eng.Fouad它抛出了它还是说你需要捕捉它?在web上有很多这样的例子。是的,它抛出了实例化异常
。您可以自己尝试:)如果您想避免掩盖构造函数中抛出的异常,getClass().getConstructor().newInstance()
更好,因为它将构造函数中抛出的任何异常包装在InvocationTargetException
中,就像在常规方法上使用invoke()
一样。
public interface Provider<T> {
T create();
}
public abstract class Animal {
private final Provider<Animal> animalProvider;
protected Animal( ... , Provider<Animal> animalProvider) {
// ...
this.animalProvider = animalProvider;
}
public Animal breed() {
return animalProvider.create();
}
}
public class Dog extends Animal {
public Dog( ... ) {
super( ... , new DogProvider());
// ...
}
private static class DogProvider implements Provider<Animal> {
public Animal create() {
return new Dog( ... );
}
}
}
public abstract class Animal {
protected final Breed breed;
protected Animal( ... , Breed breed) {
// ...
this.breed = breed;
}
public Breed getBreed() {
return breed;
}
}
public class Dog extends Animal {
public Dog( ... ) {
super( ... , new Breed( ... ));
// ...
}
}