在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( ... ));
        // ...
    }
}