【问题标题】:Implementing clone() in a subclass在子类中实现 clone()
【发布时间】:2012-08-26 03:43:10
【问题描述】:

我有两个类:父类 A 和一些子类 B,它扩展了 A 并且比 A 多了几个字段。我希望能够克隆这两个类,所以我重写了 clone() 方法Object 类。

由于 B 类基本上是带有一些额外字段的 A 类,因此我想在 B 类的 clone() 实现中使用 A 类的克隆。我尝试了以下内容:

    public class A
    {
      public Object clone()
      {
        A cloneA = new A();
        cloneA.foo = this.foo;
        cloneA.bar = this.bar;
        return cloneA;
      }
    }

    public class B extends B
    {
      public Object clone()
      {
        Object cloneA = super.clone();
        B cloneB = (B)cloneA;
        cloneB.fieldSpecificForB = this.fieldSpecificForB;
        return cloneB;
      }
    }

这样我就不必在 B 的 clone() 方法中复制 A 的 clone() 方法中的所有克隆逻辑。不幸的是,这不起作用,因为 Java 不允许将 A 类的对象强制转换为 B 类的对象。我四处寻找有关如何执行此操作的答案,但似乎没有办法重用来自的克隆逻辑A.这是否意味着每次我在A中添加另一个字段时,我都必须手动将这个字段的复制添加到所有子类的clone()方法中。这似乎很容易出错...

【问题讨论】:

标签: java inheritance clone


【解决方案1】:

clone 的工作方式是自动为您复制所有字段。但是,您必须致电 super.clone() 才能使其工作:

public class A implements Cloneable  // add 'implements'
{
  public Object clone()
  {
    A cloneA = super.clone(); // this copies all fields and returns something of *the same type* as 'this'...
    return cloneA;
  }
}

public class B extends A //supposed to extend 'A' right?
{
  public Object clone()
  {
    Object cloneA = super.clone(); // this returns object of runtime type B
    B cloneB = (B)cloneA; // will work
    return cloneB;
  }
}

编辑:实际上你的 clone 方法现在什么都不做,所以它相当于写:

public class A implements Cloneable  //add 'implements'
{

}

public class B extends A //supposed to extend 'A' right?
{

}

implements Cloneable 部分可以解决问题。另见Cloneable

【讨论】:

  • 感谢您的回答。我注意到我在我的 OP 中犯了一些错误(主要是 B 没有扩展 A 和 A.clone() 没有返回任何东西)。看来我误解了 Cloneable 接口和 super.clone() 的工作方式。这次我将尝试使用您的示例来实现它。
【解决方案2】:

问题在于您对A#clone() 的实现。您永远不应该使用new 创建您将在clone 方法中返回的实例,而是始终通过调用super.clone() 来创建,以避免您现在遇到的错误。

所以将你的 A 类调整为

public class A
{
  @Override
  protected Object clone() throws CloneNotSupportedException
  {
    A cloneA = (A)super.clone();
    cloneA.foo = this.foo;
    cloneA.bar = this.bar;
    return cloneA;
  }
}

【讨论】:

  • 如果层次结构上的所有类都通过调用super.clone() 来构造新对象,你的应该这样做,但如果它们中的任何一个通过调用复制构造函数来构造新对象,你的也必须这样做。我觉得应该使用复制构造函数的想法令人讨厌,因为clone 从根本上被破坏了,因为整个原因它首先被“破坏”是相信复制构造函数在某种程度上更好。跨度>
猜你喜欢
  • 2012-07-06
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-27
  • 1970-01-01
相关资源
最近更新 更多