2012-05-09 62 views
1

我有一个抽象超类和一些派生类。
我想在派生类中它将创建的所有成员的智能副本衍生一个新的实例调用时创建的方法需要java继承设计小技巧

createNew() 


所有对创建重要的成员都在抽象类中,因此代码应该是相同的。
我可以在超类中编写createNew()的实现吗?

类似的东西

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

的ABS超应该做的实现,因为该代码是相同的。
谢谢。

回答

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; 
    } 
} 
+0

是不是实际的C#代码?你不应该使用“扩展”而不是:? – david99world

+0

@ david99world糟糕,你是对的 - 我最近做了太多的C#。现在已修复,谢谢! – dasblinkenlight

1

制作一个抽象方法,将用作您的createNew方法所使用的回调 - 并在每个子类中实现方法。 createNew可以是普通超类的具体方法,即使是final方法。提到的抽象方法将返回相应子类的新实例。

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

+0

注意,在OP的示例'SonA.createNew()'和'SonB。 createNew()'有不同的返回类型。 – NPE

+0

@aix不一定,它可能是' createNew()'。它将用于特定的用例,但是在更复杂的表达式中它不会被使用。 –

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 ... 
    } 
} 

您可能还需要阅读有关copy constructors

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; 
    } 
}