【问题标题】:Mandatory cloneable interface in JavaJava中的强制可克隆接口
【发布时间】:2008-10-27 17:40:18
【问题描述】:

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

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

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

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

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

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

谢谢,

纪尧姆。

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

【问题讨论】:

    标签: java interface overriding clone


    【解决方案1】:

    如果您使用的是 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 方法的结果。

    【讨论】:

      【解决方案2】:

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

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

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

      另外,你不能覆盖接口上的类:

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

      【讨论】:

        【解决方案3】:

        添加到 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 对其进行测试,因为我没有安装它,但我想它可以正常工作。

        【讨论】:

        • 你是对的。不错的小技巧!正如您所怀疑的,它在 Java 5 中可以正常工作。
        【解决方案4】:

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

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

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            【解决方案6】:

            公共类 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();
            
            }
            

            }

            【讨论】:

              猜你喜欢
              • 2016-06-27
              • 1970-01-01
              • 2011-10-07
              • 2012-07-13
              • 1970-01-01
              • 2023-03-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多