4

我在 Java 中遇到了一个小问题。我有一个名为 Modifiable 的接口。实现此接口的对象是可修改的。

我还有一个 ModifyCommand 类(带有命令模式),它接收两个 Modifiable 对象(在列表中进一步交换它们 - 这不是我的问题,我已经设计了那个解决方案)。

ModifyCommand 类首先复制 Modifiable 对象。从逻辑上讲,我让我的 Modifiable 接口扩展了 Cloneable。然后接口定义了一个 clone() 方法,它的实现类必须重新定义。

然后,在 ModifyCommand 中,我可以这样做:firstModifiableObject.clone()。我的逻辑是实现 Modifiable 的类必须重新定义 Object 的 clone 方法,因为它们将是 Cloneable (这就是我想要做的)。

问题是,当我定义类实现 Modifiable 并且我想重写 clone() 时,它不会让我说 Object 类中的 clone() 方法隐藏了 Modifiable 中的方法。

我该怎么办?我的印象是“我做错了”......

谢谢,

纪尧姆。

编辑:它认为我会忘记 clone() 的事情。我将a)假设传递给Modifiable对象(实现接口)的对象已经被克隆或b)创建另一个称为copy()的方法,该方法基本上会对Modifiable对象进行深层复制(或者通用解决方案可能会起作用......)。

4

6 回答 6

10

如果您使用的是 java 1.5 或更高版本,则可以通过以下方式获得所需的行为并删除强制转换:

public interface Modifiable<T extends Modifiable<T>> extends Cloneable {
    T clone();
}

public class Foo implements Modifiable<Foo> {
    public Foo clone() { //this is required
        return null; //todo: real work
    }
}

由于 Foo 扩展了 Object,这仍然满足 Object 类的原始约定。由于 Modifiable 接口施加的额外约束,未正确优化 clone() 方法的代码将无法编译。作为奖励,调用代码不必强制转换 clone 方法的结果。

于 2008-10-27T18:08:58.300 回答
1

您不需要在接口 Modifiable 上重新定义 clone 方法。

检查文档:http: //java.sun.com/j2se/1.4.2/docs/api/java/lang/Cloneable.html

我了解您试图强​​迫所有人覆盖克隆方法(),但您不能这样做。

在另一种方式中,您不能覆盖接口上的类:

clone() 方法始终与 Object.class 相关联,而不是与可克隆接口相关联。您可以在另一个对象上覆盖它,而不是在界面中。

于 2008-10-27T17:51:21.223 回答
1

添加到 Sean Reilly 的答案中,这应该可以解决您的问题,并且类型更安全。它在 JDK6 上编译并运行良好:

public interface Modifiable<T extends Modifiable<T>> extends Cloneable {
    T clone();
}
public class Test implements Modifiable<Test> {
    @Override
    public Test clone() {
        System.out.println("clone");
        return null;
    }
    public static void main(String[] args) {
        Test t = new Test().clone();
    }
}

我无法使用 Java 5 对其进行测试,因为我没有安装它,但我想它可以正常工作。

于 2008-12-23T06:44:37.147 回答
0

您是否完全按照对象中的方式定义了签名?

public Object clone() throws CloneNotSupportedException {
    return super.clone();
}

这应该编译 - 将自定义代码添加到正文。 维基百科在这方面提供了惊人的帮助。

于 2008-10-27T17:47:37.737 回答
0

您的克隆方法的方法签名是什么样的?为了匹配 Clonable 接口,它必须返回一个对象。如果您将其声明为返回 Modifiable 则可能是问题所在。

于 2008-10-27T17:48:37.407 回答
0

公共类 CloningExample 实现 Cloneable {

private LinkedList names = new LinkedList();


public CloningExample() {
    names.add("Alex");
    names.add("Melody");
    names.add("Jeff");
}


public String toString() {
    StringBuffer sb = new StringBuffer();
    Iterator i = names.iterator();
    while (i.hasNext()) {
        sb.append("\n\t" + i.next());
    }
    return sb.toString();
}


public Object clone() {
    try {
        return super.clone();
    } catch (CloneNotSupportedException e) {
        throw new Error("This should not occur since we implement Cloneable");
    }
}


public Object deepClone() {
    try {
        CloningExample copy = (CloningExample)super.clone();
        copy.names = (LinkedList)names.clone();
        return copy;
    } catch (CloneNotSupportedException e) {
        throw new Error("This should not occur since we implement Cloneable");
    }
}

public boolean equals(Object obj) {

    /* is obj reference this object being compared */
    if (obj == this) {
        return true;
    }

    /* is obj reference null */
    if (obj == null) {
        return false;
    }

    /* Make sure references are of same type */
    if (!(this.getClass() == obj.getClass())) {
        return false;
    } else {
        CloningExample tmp = (CloningExample)obj;
        if (this.names == tmp.names) {
            return true;
        } else {
            return false;
        }
    }

}


public static void main(String[] args) {

    CloningExample ce1 = new CloningExample();
    System.out.println("\nCloningExample[1]\n" + 
                       "-----------------" + ce1);

    CloningExample ce2 = (CloningExample)ce1.clone();
    System.out.println("\nCloningExample[2]\n" +
                       "-----------------" + ce2);

    System.out.println("\nCompare Shallow Copy\n" +
                       "--------------------\n" +
                       "    ce1 == ce2      : " + (ce1 == ce2) + "\n" +
                       "    ce1.equals(ce2) : " + ce1.equals(ce2));

    CloningExample ce3 = (CloningExample)ce1.deepClone();
    System.out.println("\nCompare Deep Copy\n" +
                       "--------------------\n" +
                       "    ce1 == ce3      : " + (ce1 == ce3) + "\n" +
                       "    ce1.equals(ce3) : " + ce1.equals(ce3));

    System.out.println();

}

}

于 2009-05-14T03:11:52.777 回答