Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
需要java继承设计技巧_Java_Inheritance - Fatal编程技术网

需要java继承设计技巧

需要java继承设计技巧,java,inheritance,Java,Inheritance,我有一个抽象超类和几个派生类。 我想创建一个方法 createNew() 在派生类上调用时,它将创建派生类的一个新实例及其所有成员的智能复制。 所有对创建非常重要的成员都在抽象类中,因此代码应该相同。 我可以在超类中编写createNew()的实现吗 诸如此类 SonA sonA2 = sonA1.createNew() SonB sonB2 = sonB1.createNew() abs超类应该执行此实现,因为代码相同。 谢谢 创建一个抽象方法,作为createNew方法使

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

createNew()   
在派生类上调用时,它将创建派生类的一个新实例及其所有成员的智能复制。
所有对创建非常重要的成员都在抽象类中,因此代码应该相同。
我可以在超类中编写createNew()的实现吗

诸如此类

SonA sonA2 = sonA1.createNew()   
SonB sonB2 = sonB1.createNew()  
abs超类应该执行此实现,因为代码相同。

谢谢

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


另一种方法是通过反射找出调用了哪个类
createNew
,并在此基础上创建一个新实例。

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


另一种方法是通过反射找出调用了哪个类
createNew
,并在此基础上创建一个新实例。

实现应该在抽象类和具体类之间划分。您可以使用模板方法模式执行此操作:

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

实现应该分为抽象类和具体类。您可以使用模板方法模式执行此操作:

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;
    }
}
您可以编写此代码(使用反射:
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 ...
     }
 }
您可能还想阅读。

您可以编写以下代码(使用反射:
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()
”调用该方法:


一种可能是将复制因素分解到一个单独的方法中,并从派生类“
createNew()
”调用该方法:


请注意,在OP的示例中,
SonA.createNew()
SonB.createNew()
有不同的返回类型。@aix不一定是
createNew()
。它将适用于特定的用例,但在更复杂的表达式中它将没有用处。请注意,在OP的示例中,
SonA.createNew()
SonB.createNew()
具有不同的返回类型。@aix不一定是
createNew()
。它将适用于特定的用例,但在更复杂的表达式中它将没有用处。这不是真正的c代码吗?你不应该使用“扩展”而不是:?@david99world Oops,你说得对-我最近做了太多的C#。现在已经修好了,谢谢!这不是c代码吗?你不应该使用“扩展”而不是:?@david99world Oops,你说得对-我最近做了太多的C#。现在已经修好了,谢谢!