Вопрос

Я пытаюсь внедрить clone() Метод на DoubleLinkedList. Анкет Теперь проблема в том, что реализация его «конвенцией» намного более хлопотно, чем просто создание нового DoubleLinkedList и заполнить его всеми элементами моего нынешнего DoubleLinkedList.

Есть ли какие -то неудобные, которые я не вижу, когда делаю это?

Вот мой текущий подход:

@Override
public DoubleLinkedList<T> clone() {
    DoubleLinkedList<T> dll = new DoubleLinkedList<T>();

    for (T element : dll) {
        dll.add(element);
    }

    return dll;
}

Вот что было бы по соглашению:

@Override
public DoubleLinkedList<T> clone() {
    try {
        DoubleLinkedList<T> dll = (DoubleLinkedList<T>)super.clone();
        //kinda complex code to copy elements
        return dll;
    } catch (CloneNotSupportedException e) {
        throw new InternalError(e.toString());
    }
}
Это было полезно?

Решение

Когда вы правильно указываете, соглашение всегда звонить super.clone() В начале реализации clone(). Анкет От API документы на Object#clone():

По соглашению возвращаемый объект должен быть получен путем вызова Super.clone. Если класс и все его суперклассы (кроме объекта) подчиняются этому соглашению, это будет тот случай, когда x.clone (). GetClass () == x.getClass ().

Ваша первая попытка (без использования super.clone()) имеет следующую проблему:

Предположим, у меня есть

class IntDoubleLinkedList extends DoubleLinkedList<Integer> implements Cloneable

(и это IntDoubleLinkedList не пытается переопределять clone()) и я запускаю следующий код:

IntDoubleLinkedList idll = new IntDoubleLinkedList();
IntDoubleLinkedList idll2 = (IntDoubleLinkedList) idll.clone();

Что случится? Метод клона ваш DoubleLinkedList будет выполнено, что, если он не пройдет через Super.Clone (), возвращает экземпляр DoubleLinkedList который, в свою очередь, не может быть поднят на IntDoubleLinkedList. А ClassCastException будет брошен!

Так как это super.clone() решить эту проблему? Ну, если все придерживаются соглашения о звонке super.clone() в методе переопределения клонов, Object.clone() в конечном итоге будет вызвана, и эта реализация создаст экземпляр надлежащего типа (IntDoubleLinkedList в таком случае)!

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

Как объяснили другие, если вы собираетесь переопределить clone Вы должны подчиняться его контракту.

Если вам нравится, как у вас есть в настоящее время, просто сделайте DoubleLinkedList нет Cloneable и превратите свою реализацию в конструктор копирования или метод статического завода. Статический фабричный метод имеет дополнительное преимущество в предоставлении небольшого типа вывода для общих аргументов.

Пса LinkedList является Список вдвойне связанный.

Если вы сделаете это, создав новый список и добавив все элементы из источника, если вы сделаете что -то вроде:

DoubleLinkedList<Foo> l1 = new DoubleLinkedList<Foo>();
l1.add (new Foo(params));
DoubleLinkedList<Foo> l2 = l1.clone();
Foo foo = l2.get(0);
foo.setProperty("new Value");

Foo.Property будет «новым значением» в обоих списках (наоборот, наоборот; если вы измените его в L1, изменения появятся в L2). Правильным способом будет то, чтобы фактически клонировать каждый элемент, и добавить клон, чтобы убедиться, что списки являются независимыми. Обратите внимание, что это происходит только в том случае, если вы измените свойства элементов, а не в том случае, если вы добавите, перемещайте, удалите их из списка.

РЕДАКТИРОВАТЬ: только что понял, что, поскольку это связанный список, следующие/предыдущие элементы являются свойствами элемента, поэтому даже добавление, удаление, повлияет на оба списка.

Причина, по которой «Конвенция» состоит в том, чтобы позвонить super.clone() это обеспечить, чтобы конечный тип клонированного объекта соответствует клонированию объекта. Например, если вы создаете свой новый новый DoubleLinkedList в clone() Метод, ну, это хорошо, но позже, если подкласс не может переопределить clone() в конечном итоге вернет клон, который DoubleLinkedList вместо собственного класса. (Это также не сможет клонировать свои дополнительные поля, если таковые имеются, вероятно, так что есть большие проблемы.)

В этом смысле обычный метод является предпочтительным, и он действительно неуклюжий.

Обе реализации, однако, имеют аналогичную проблему: вы не глубоко укорените структуры данных. Клон - это всего лишь мелкий полицейский. Это, вероятно, не то, что ожидает вызывающий абонент. Вам нужно пройти и заменить каждое значение в DoubleLinkedList с клоном значения, а также для других невимичных полей.

В этом смысле обычный метод даст здесь неправильный результат! Вам нужен третий путь. Ваш первый метод, вероятно, просто работает, за исключением того, что вам нужно добавить element.clone() Например.

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