Вопрос

У меня возникла небольшая проблема в Java.У меня есть интерфейс, который называется Изменяемым.Объекты, реализующие этот интерфейс, могут быть изменены.

У меня также есть класс ModifyCommand (с шаблоном Command), который получает два изменяемых объекта (чтобы поменять их местами в списке далее - это не мой вопрос, я уже разработал это решение).

Класс ModifyCommand начинается с создания клонов изменяемых объектов.По логике вещей, я сделал свой Изменяемый интерфейс extends Клонируемым.Затем интерфейс определяет метод clone(), который его реализующие классы должны переопределить.

Затем, в ModifyCommand, я могу сделать :firstModifiableObject.clone().Моя логика заключается в том, что классы, реализующие Modifiable, должны будут переопределить метод clone из Object, поскольку они будут клонируемыми (это то, что я хочу сделать).

Дело в том, что когда я определяю classes implements Modifiable и хочу переопределить clone(), это мне не позволяет, заявляя, что метод clone() из класса Object скрывает метод из Modifiable.

Что мне следует делать?У меня создается впечатление, что "я делаю это неправильно"...

Спасибо,

Гийом.

Редактировать :он думает, что я забуду о clone() .Я либо а) предположу, что объект, переданный Изменяемому объекту (реализующему интерфейс), уже клонирован, либо б) создам другой вызываемый метод, например copy(), который в основном выполнит глубокую копию Изменяемого объекта (или, возможно, общее решение сработает ...).

Это было полезно?

Решение

Если вы используете 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.Код, который неправильно уточняет метод clone(), не будет компилироваться из-за дополнительных ограничений, налагаемых изменяемым интерфейсом.В качестве бонуса, вызывающий код не должен приводить результат метода clone.

Другие советы

Вам не нужно переопределять метод clone в изменяемом интерфейсе.

Проверьте документацию: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Cloneable.html

Я понимаю, что вы пытаетесь заставить всех переопределить метод clone(), но вы не можете этого сделать.

Другим способом вы не можете переопределить класс в интерфейсе:

Метод clone() всегда связан с Object.class, а не с клонируемым интерфейсом.Вы просто можете переопределить его на другом объекте, а не в интерфейсе.

Добавляя к ответу Шона Рейли, это должно решить вашу проблему и является более типобезопасным.Он компилируется и отлично работает у меня на 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, потому что у меня он не установлен, но я думаю, что он будет работать нормально.

Определили ли вы подпись точно так, как она есть в object?

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

Это должно скомпилировать - добавить пользовательский код в тело. Википедия был на удивление полезен в этом вопросе.

Как выглядит сигнатура вашего метода для вашего метода clone?Чтобы он соответствовал клонируемому интерфейсу, он должен был бы вернуть объект.Если вы объявляете его как возвращающий Изменяемый, то это может быть проблемой.

публичный класс 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();

}

}

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top