Обязательный клонируемый интерфейс в Java - PullRequest
4 голосов
/ 27 октября 2008

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

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

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

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

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

Что мне делать? У меня сложилось впечатление, что «я делаю это неправильно» ...

Спасибо

Гийом.

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

Ответы [ 6 ]

10 голосов
/ 27 октября 2008

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

1 голос
/ 23 декабря 2008

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

1 голос
/ 27 октября 2008

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

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

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

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

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

0 голосов
/ 14 мая 2009

открытый класс 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();

}

}

0 голосов
/ 27 октября 2008

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

0 голосов
/ 27 октября 2008

Вы определили подпись точно так же, как в объекте?

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...