我可以在 Java 中从父实例实例化相同子类型的 class 吗?

Could I instantiate class of the same child type from parent in Java?

有没有办法从 Java 中的父实例化相同子类型的 class?

例如我们有:

class Animal {
    Animal clone() {
        ...
    } 
}

class Rabbit extends Animal {
    ...
}

class Fox extends Animal {
    ...
}

如果我从 Rabbits 实例调用它,我可以在动物克隆方法中写一些东西来获取 Rabbit,如果从 Fox 调用,我可以用 Fox 获取 Rabbit 吗?我知道我可以在 Rabbit 和 Fox 中编写两个单独的克隆方法,但是是否有办法在 Animal 中编写通用方法?谢谢!

UPD: 正如我在评论中所述,我需要 PHP:

function clone (): Animal
{
    return eval("return new " . get_class($this) . " ();");
}

你可以做到...但你需要大量使用反射。

However, the right thing to do would be giving each child class its own clone method and keep the cloner() abstract method in the parent class. As you would not want the parent to be aware of all child class implementations.

(PS。克隆方法已存在于对象 class)

abstract class Animal{

//..
//..

Animal cloner();


}


abstract class Rabbit extends Animal{

//..
//..

Rabbit cloner(){
//impl
}


}



abstract class Fox extends Animal{

//..
//..

Rabbit cloner(){
//impl
}


}

你可以这样写:

Animal clone1() {
    if (this instanceof Rabbit){
      System.out.println("Returning Rabbit instance");
      return new Rabbit();
    }
    elseif (this instanceof Fox){
      System.out.println("Returning Fox instance");
      return new Fox();
    }else
      return null;
}

或者如果想使用反射并且不想每次添加新的 subclass 时都更改 super class。您可以使用 Dozer Mapper,它将映射到 new/clone 对象。见以下代码:

class Animal {

  Animal clone2(){
    Mapper mapper = new DozerBeanMapper();
    return mapper.map(this, this.getClass());
  }

}

class Rabbit extends Animal {
  int testVar = 20;
}

public class App {
  public static void main(String[] args) throws CloneNotSupportedException, IOException {
    Rabbit rabbit = new Rabbit();
    System.out.println("Object: " + rabbit.hashCode());
    System.out.println("Object var: " + rabbit.testVar);

    Rabbit rabbit2 = (Rabbit) rabbit.clone2();
    System.out.println("Clone object: " + rabbit2.hashCode());
    System.out.println("Object var: " + rabbit2.testVar);
  }

}

运行 并检查输出都具有相同的字段但是是单独的对象。 注意:您需要在您的项目中添加 dozer mapper dependency/jar。对于 Maven 检查:https://mvnrepository.com/artifact/net.sf.dozer/dozer/5.3.1

但是你为什么要这样做呢?如果你想创建克隆,原型模式是更简洁的方法。原型模式:http://www.newthinktank.com/2012/09/prototype-design-pattern-tutorial/

对于您的要求,您只需要让 JVM 知道您想要这个 class 并且它 sub-classes 是可克隆的:

class Animal implements Cloneable

并对动物、狐狸和兔子使用 Object::clone()。

有了这个,您只能获得对象的浅表副本 - 这意味着克隆对象和原始对象将共享 non-primary 字段的相同实例。

对于每个需要深拷贝的对象,您要实现专用的 clone() 方法。

有关克隆的更多信息 here .