使用可怕的克隆成语是克隆未知(子)类型对象的唯一方法吗?

时间:2015-11-17 00:24:01

标签: java cloneable

我有一个班级("经理")管理一个全部根植于一个共同超类的对象集合(" 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普遍愤怒和仇恨,但这是做我想要的最好的方式。我错过了什么吗?

3 个答案:

答案 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的强大功能来自于其继承的运行时动态行为,而复制构造函数不适用于继承。

使对象可克隆的标准方法是:

  1. 实施可克隆
  2. 覆盖clone()并公开
  3. clone()内,致电super.clone() 托管obj =(托管)super.clone();
  4. 对象的克隆将对所有字段执行简单的内存复制。这适用于基元和对不可变对象的引用。对于可变对象,您需要根据需要克隆/复制这些对象
  5. 如果继承Managed,并且子类正确实现了克隆,那么克隆它将返回正确的类型。 e.g。

    Managed m = new SubTypeOfManaged();
    m.clone(); // returns a cloned SubTypeOfManaged