我有一个班级("经理")管理一个全部根植于一个共同超类的对象集合(" Managed")。管理器类有时需要复制选定的托管对象,但无法知道托管对象的哪个子类。在我看来,最好的(如果不是?)方式是使用Cloneable。然后,对于我需要复制的任何Managed对象,我调用managedObject.clone()。当然必须正确实施。我已经阅读了许多警告,只需使用复制构造函数"或者为所有子类实现myManagedSubClass.copy()方法。我不知道如何使用"真实"复制构造函数,因为我需要知道类型:
ManagedSubclass copiedObject = new ManagedSubclass(existingManagedSubclassObject);
如果我实现copy()方法,我认为这将是这样的:
class Managed {
public Managed copy() {
Managed newObject = new Managed(Managed other);
// fixup mutable fields in newObject
}
}
但在我的使用中,我必须将返回值强制转换为预期的类型。如果我忘记在所有托管子类上实现copy(),那么我最终会将超类强制转换为子类类型。我无法在Managed上创建受复制保护的可见性,因为这是直接复制的有效类。即使不是这种情况,我也必须在每个可以复制的子类上实现副本,所有机制都可以处理可变字段的深层副本,或者建立我自己的一些常用名称的受保护方法的协议。该级别的超类引入的所有可变字段。
似乎尽管Cloneable普遍愤怒和仇恨,但这是做我想要的最好的方式。我错过了什么吗?
答案 0 :(得分:2)
适时的正确工具。
如果您需要Cloneable
,请使用它。但要知道它拥有的所有流量。
clone()
声名狼借,因为它太复杂了,它做得不好而且做得很糟糕。除非你有最后的字段或零参数构造函数调用另一个构造函数,否则你应该没问题,只要你按照建议实现它。
答案 1 :(得分:2)
我更喜欢使用复制构造函数来复制可变对象。在编写构造函数时,您必须调用JPasswordField
,在这里您可以使用超类的复制构造函数。这种调用超类的构造函数然后分配当前类的字段的方法类似于编写super(...)
方法的方式(调用clone
然后在必要时重新分配字段)。这比super.clone()
的一个优点是你永远不必使用无用的clone
结构。复制构造函数相对于使用try {...} catch (CloneNotSupportedException e) {}
的另一个优点是,您可以创建可变字段clone
,而final
要求您在调用clone
后使用其副本重新分配字段原始
在编写super.clone()
方法时不能使用继承,因为copy
返回超类的实例。但是,如果您喜欢使用方法而不是构造函数,那么除了复制构造函数之外,您还可以提供super.copy()
方法。
这是一个例子。
copy
答案 2 :(得分:0)
Clone的强大功能来自于其继承的运行时动态行为,而复制构造函数不适用于继承。
使对象可克隆的标准方法是:
clone()
并公开clone()
内,致电super.clone()
托管obj =(托管)super.clone(); 如果继承Managed
,并且子类正确实现了克隆,那么克隆它将返回正确的类型。 e.g。
Managed m = new SubTypeOfManaged();
m.clone(); // returns a cloned SubTypeOfManaged