我有一个抽象超类和一些派生类。
我想创建一个方法
createNew()
当在派生类上调用时,它将创建派生类的新实例,其中包含其所有成员的智能副本。
对创建很重要的所有成员都在抽象类中,因此代码应该相同。
我可以在超类中编写 createNew() 的实现吗?
类似的东西
SonA sonA2 = sonA1.createNew()
SonB sonB2 = sonB1.createNew()
abs 超类应该执行实现,因为代码是相同的。
谢谢。
我有一个抽象超类和一些派生类。
我想创建一个方法
createNew()
当在派生类上调用时,它将创建派生类的新实例,其中包含其所有成员的智能副本。
对创建很重要的所有成员都在抽象类中,因此代码应该相同。
我可以在超类中编写 createNew() 的实现吗?
类似的东西
SonA sonA2 = sonA1.createNew()
SonB sonB2 = sonB1.createNew()
abs 超类应该执行实现,因为代码是相同的。
谢谢。
实现应该分为抽象类和具体类。您可以使用模板方法模式来做到这一点:
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;
}
}
创建一个抽象方法,作为您的方法使用的回调——并在每个子类中createNew
实现该方法。createNew
可以是final
公共超类的具体的,甚至是方法。提到的抽象方法将返回相应子类的新实例。
另一种方法是通过反射找出createNew
调用了哪个类并基于它创建一个新实例。
您可以编写此代码(使用反射: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 ...
}
}
您可能还想阅读有关复制构造函数的内容。
一种可能性是将复制因素考虑到一个单独的方法中,并从派生类中调用它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;
}
}