1

我有一个抽象超类和一些派生类。
我想创建一个方法

createNew()   

当在派生类上调用时,它将创建派生类的新实例,其中包含其所有成员的智能副本。
对创建很重要的所有成员都在抽象类中,因此代码应该相同。
我可以在超类中编写 createNew() 的实现吗?

类似的东西

SonA sonA2 = sonA1.createNew()   
SonB sonB2 = sonB1.createNew()  

abs 超类应该执行实现,因为代码是相同的。
谢谢。

4

4 回答 4

3

实现应该分为抽象类和具体类。您可以使用模板方法模式来做到这一点:

public abstract class AbstractSon {
    protected abstract AbstractSon createNewImpl();
    public AbstractSon createNew() {
        AbstractSon res = createNewImpl();
        res.name = "default name";
        return res;
    }
}
public class Son1 extends AbstractSon {
    protected AbstractSon createNewImpl() {
        return new Son1();
    }
}
public class Son2 extends AbstractSon {
    protected AbstractSon createNewImpl() {
        return new Son2();
    }
}

您可以以不同的方式拆分职责以获得精确的返回类型:

public abstract class AbstractSon {
    protected void prepare(AbstractSon toPrepare) {
        toPrepare.name = "default name";
    }
}
public class Son1 extends AbstractSon {
    public Son1 createNew() {
        Son1 res = new Son1();
        prepare(res);
        return res;
    }
}
public class Son2 extends AbstractSon {
    public Son2 createNew() {
        Son2 res = new Son2();
        prepare(res);
        return res;
    }
}
于 2012-05-09T14:03:31.517 回答
1

创建一个抽象方法,作为您的方法使用的回调——并在每个子类中createNew实现该方法。createNew可以是final公共超类的具体的,甚至是方法。提到的抽象方法将返回相应子类的新实例。

另一种方法是通过反射找出createNew调用了哪个类并基于它创建一个新实例。

于 2012-05-09T14:01:53.653 回答
1

您可以编写此代码(使用反射:getClass().newInstance()获取实际类的实例,而不是定义方法的类),但它有一些问题。例如,您打算从此方法返回什么?

您必须返回超类型,这意味着您必须为每次调用进行强制转换。

通常的解决方案是定义一个copy()您在每个级别上定义的方法。然后你可以这样做:

 class SonA {
     SonA createNew() {
         SonA result = new SonA();
         this.copy( result );
         return result;
     }

     void copy( SonA target ) {
         super.copy( target );

         // copy my fields to target ...
     }
 }

您可能还想阅读有关复制构造函数的内容。

于 2012-05-09T14:03:52.033 回答
1

一种可能性是将复制因素考虑到一个单独的方法中,并从派生类中调用它createNew()

abstract class Base {

  public abstract Base createNew();

  protected void populate(Base out) {
    // copy the data from `this' to `out'
  }
}

class Derived1 extends Base {
  public Derived1 createNew() {
    Derived1 ret = new new Derived1();
    populate(ret);
    return ret;
  }
}

class Derived1 extends Base {
  public Derived2 createNew() {
    Derived2 ret = new new Derived2();
    populate(ret);
    return ret;
  }
}
于 2012-05-09T14:06:37.103 回答