在网上搜索如何以多态方式制作对象的深层副本时,我发现solution声称使用clone()
方法解决了许多问题,例如克隆final
字段是不可能的。该解决方案结合了clone()
实现中受保护的复制构造函数的使用,基本上就是这样(从引用页面复制的示例):
public class Person implements Cloneable
{
private final Brain brain; // brain is final since I do not want
// any transplant on it once created!
private int age;
public Person(Brain aBrain, int theAge)
{
brain = aBrain;
age = theAge;
}
protected Person(Person another)
{
Brain refBrain = null;
try
{
refBrain = (Brain) another.brain.clone();
// You can set the brain in the constructor
}
catch(CloneNotSupportedException e) {}
brain = refBrain;
age = another.age;
}
public Object clone()
{
return new Person(this);
}
…
}
clone()
的{{1}}方法可能会以类似的方式实施。
基于documentation of the clone()
method,这个方法的所有“契约”似乎都不是“绝对要求”,并且“通过调用Brain
获得返回的对象”只是一种约定。
那么,这个实现实际上是不正确的吗?为什么呢?
如果它是正确的,为什么它不会成为一种设计模式?这有什么缺点???
谢谢,彼得
答案 0 :(得分:1)
您尝试通过实现可克隆接口进行克隆,但不遵循建议的克隆合同。
你基本上是使用复制构造函数创建新对象,我的问题是你为什么需要实现cloneable?
如果您正在实施克隆,那么您必须尊重合同。当你在克隆方法中使用复制构造函数时,我不会推荐这种方法,因为它的子类的克隆不会是子类的对象,而且它将成为Person类的一个对象。
另外要指出的是,使用复制构造函数而不是克隆接口是更加面向对象的方法。
答案 1 :(得分:0)
那么,这个实现实际上是不正确的吗?为什么呢?
这不安全,因为CloneNotSupportedException被删除。
如果Brain不能克隆,那么新人就没有脑子:) 如果您的对象结构中有一个您无法控制的对象(无法访问源),该怎么办?
为什么它没有成为一种设计模式
因为并非所有对象都可以从类似对象中克隆。通常,有一些环境对象可以更好地了解这个特定的新对象的外观,而不是现有的邻居对象。
答案 2 :(得分:0)
此方法的缺点(除了CloneNotSupportedException
被删除的事实)是,如果子类调用super.clone()
,它们将获得Person
的实例而不是它们自己的实例他们可能期望上课。
如果您知道子类不依赖Object.clone()
(或者没有子类),那么您的方法就可以了