Что не так с этим клоном ()?

Для создания хорошо документированного кода требуется меньше времени, чем для плохо документированного кода

Когда я говорю хорошо документирован , я имею в виду комментарии, которые сообщают о вашем намерении. четко на каждом шагу. Да, ввод комментариев занимает некоторое время. И да, ваши коллеги должны быть достаточно умны, чтобы понять, что вы хотели, просто прочитав вашу описательную функцию и имена переменных и тщательно продумав все свои исполняемые операторы. Но на это уходит больше времени, чем если бы вы только что объяснили свои намерения, и ясная документация особенно полезна, когда логика кода оказывается неверной. Не то чтобы ваш код был бы неверным ...

Я твердо верю, что если вы рассчитываете время от начала проекта до поставки бездефектного продукта, написание хорошо документированного кода займет меньше времени. Во-первых, необходимость четко объяснять, что вы делаете, заставляет вас четко обдумать это, и если вы не можете написать ясное, краткое объяснение того, что выполняет ваш код, то, вероятно, он не разработан должным образом. И по другой, исключительно эгоистичной причине, хорошо документированный и хорошо структурированный код гораздо проще перенести на кого-то другого, чтобы поддерживать - таким образом, освобождая первоначального автора для создания следующей важной вещи. Я редко, если когда-либо, вынужден останавливать то, что я делаю, чтобы объяснить, как мой код должен был работать, потому что он очевиден для любого, кто умеет читать по-английски (даже если он не умеет читать C / C ++ / C # и т. Д.). И еще одна причина, честно говоря, моя память просто не так хороша! Я не могу вспомнить, что у меня было на завтрак вчера, тем более, о чем я думал, когда писал код месяц или год назад. Возможно, ваша память намного лучше моей, но, поскольку я документирую свои намерения, я могу быстро подобрать, где бы я ни остановился, и внести изменения без необходимости сначала выяснить, о чем я думал, когда писал это.

Вот почему я хорошо документирую - не потому, что я чувствую какой-то благородный призыв к созданию красивого кода, пригодного для отображения, и не потому, что я пурист, а просто потому, что он позволяет мне поставлять качественное программное обеспечение за меньшее время .

6
задан Kevin Montrose 7 August 2009 в 06:11
поделиться

9 ответов

Реализовали ли вы интерфейс Cloneable для своего объекта?

Однако есть очень мало случаев, когда я бы использовал clone для копирования объекта. Один из таких безопасных примеров - array.clone (). Я бы предпочел использовать идиому копирующего конструктора или вручную копировать / присваивать значения.

В Эффективная Java (2-е издание) есть пункт № 11 о фоновой проблеме. Клонируемый интерфейс - это особый вид интерфейса, поскольку он изменяет поведение класса Object в отношении клонирования. По сути, это функция, включающая интерфейс class в Java.

Изменить: На основе вашего примера вам может потребоваться заключить вызов clone () в try-catch CloneNotSupportedException в общем случае .

Edit2: Перефразировал мой ответ

Edit3: Вы переопределили clone () в общедоступном контексте? В приведенном вами примере вы пытаетесь клонировать объект, который находится в пакете java.lang - вряд ли это пакет, в котором находится ваш код.

Edit4: Я думаю, что ответ уже есть в других сообщениях, просто хотел чтобы поразмышлять над основной проблемой.

Edit5: Попробуйте следующее:

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

Edit6 Затем назовите свой метод public abstract Object copy () , например, и в реализации используйте super.clone () - во избежание путаницы.

Edit7 Я сделал несколько затмений и пришел со следующим решением:

public class Cloner {
    public static abstract class Person {
       protected abstract Object clone1() throws CloneNotSupportedException;
       public Object copy() throws CloneNotSupportedException {
           return clone1();
       }
    }
    public static class Employee extends Person implements Cloneable {
        @Override
        protected Object clone1() throws CloneNotSupportedException {
            return super.clone();
        }

    }
    public static void main(String[] args) throws Exception {
        new Employee().copy();
    }
}

Но в основном это та же концепция, что и переименование вашего абстрактного метода во что-то другое, кроме clone ( ).

Edit8: Исправил мой пример, теперь работает без исключения.

2
ответ дан 8 December 2019 в 03:40
поделиться

Стандартный шаблон для создания клонируемого класса:

  1. Реализовать Клонируемый
  2. Заменить метод clone () и сделать его общедоступным
  3. В clone () вызовите super.clone () , а затем скопируйте состояние любого изменяемого объекта

Вы должны не создавать новый объект, используя new . Правильный способ - вызвать super.clone () для нового экземпляра. clone () объекта является особенным и создает новую копию объекта и копирует его примитивные поля и ссылки.

Например:

public class Person implements Cloneable {
    protected String name;
    // Note that overridden clone is public
    public Object clone() {
        Person clone = (Person)super.clone();
        // No need to copy name as the reference will be
        // copied by Object's clone and String is immutable
        return clone;
    }
}

public class Employee extends Person {
    protected int id;
    protected java.awt.Point location;
    public Object clone() {
        Employee  clone = (Employee )super.clone();
        // No need to copy id as Object's clone has already copied it
        // Need to clone location as Point is mutable and could change
        clone.location = location.clone();
        return clone;
    }
}
11
ответ дан 8 December 2019 в 03:40
поделиться

Java ' механизм клонирования несколько неудобен. Чтобы иметь возможность клонировать себя, класс должен делать две вещи. Сначала он должен реализовать Clonable. Во-вторых, он должен переопределить clone () и сделать его общедоступным.

В вашем примере вы переопределяете clone (), но вызываете clone () не в классе Employee, а в Object.class (), где clone () - только охраняется.

6
ответ дан 8 December 2019 в 03:40
поделиться

Мистер Блох из Effective Java может сказать несколько интересных слов об использовании клона .

http://www.artima.com/intv/bloch13. html

Обычно в настоящее время принято избегать использования клона, поскольку он подвержен ошибкам и неправильно понимается, реализация конструктора копирования является альтернативной стратегией или использование подхода грубой силы для глубокого копирования объекта с использованием сериализации.

4
ответ дан 8 December 2019 в 03:40
поделиться

Вам следует просто написать

return super.clone(); 

в вашем методе клонирования и реализовать интерфейс Clonable.

2
ответ дан 8 December 2019 в 03:40
поделиться

Реализовали ли вы соответствующий интерфейс? Это может быть так просто, хотя вы, возможно, уже это учли.

См. Здесь для получения дополнительной информации: http://java.sun.com/javase/6/docs/api/java/lang /Object.html#clone()[121pting

0
ответ дан 8 December 2019 в 03:40
поделиться

Я не очень знаком с Java, но это может помочь: http://en.wikipedia.org/wiki/Clone_ (Java_method)

Выдержка из сообщения:

Еще одним недостатком является то, что часто не может получить доступ к методу clone () на абстрактный тип. Большинство интерфейсов и абстрактные классы в Java не укажите общедоступный метод clone (). Как результат, часто единственный способ использовать clone (), если вы знаете актуальный класс объекта; который вопреки принципу абстракции использования наиболее общего типа возможно. Например, если у кого-то есть Ссылка на список в Java, нельзя вызвать clone () по этой ссылке потому что в списке нет общедоступных clone () метод. Актуальные реализации списка, такого как ArrayList и LinkedList у всех обычно есть методы clone () себя, но это неудобно и плохая абстракция носить с собой фактический тип класса объекта.

0
ответ дан 8 December 2019 в 03:40
поделиться

В основном, чтобы иметь правильно клонируемый объект, достаточно иметь в этом классе реализованный общедоступный метод clone ().

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

Чтобы правильно реализовать метод клонирования для класса, вы должны объявить клон общедоступного метода, как это ().

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

Хорошая работающая реализацияk создаст новый объект и правильно назначит поля, как того требует бизнес-логика:

public Object clone() {
   CurrentClass newObject = new CurrentClass();

   newObject.field1 = this.field1; // for simple types: int, long, etc
   newObject.referenceField = this.referenceField.clone(); // for agregate objects or references.
   return newObject;
}

Заключение: объявить общедоступный метод клонирования. Если вы хотите иметь реализацию по умолчанию в виде поля с помощью функции копирования поля, вызовите super и отметьте класс как Cloneable Если вы хотите только индивидуальное клонирование, игнорируйте метку «Клонируемый».

-2
ответ дан 8 December 2019 в 03:40
поделиться

Я думаю, что текущий зеленый ответ плохой , почему вы можете спросить?

  • Он добавляет много кода
  • Он требует, чтобы вы перечислили все поля для копирования и сделать это
  • Это не будет работать для списков при использовании clone () (Это то, что говорит clone () для HashMap: возвращает неглубокую копию этого экземпляра HashMap: сами ключи и значения не клонируются.) Так что вы в конечном итоге делаете это вручную (это заставляет меня плакать)

Да, кстати, сериализация - тоже плохо, возможно, вам придется добавлять Serializable повсюду (это тоже заставляет меня плакать).

Итак, каково решение:

Библиотека глубокого клонирования Java Библиотека клонирования - это небольшая java-библиотека с открытым исходным кодом (лицензия apache), которая глубоко клонирует объекты. Объекты не обязательно должны реализовывать интерфейс Cloneable. Фактически, эта библиотека может клонировать ЛЮБЫЕ объекты Java. Его можно использовать, например, в реализациях кеширования, если вы не хотите, чтобы кэшированный объект изменялся или всякий раз, когда вы хотите создать глубокую копию объектов.

Cloner cloner=new Cloner();
XX clone = cloner.deepClone(someObjectOfTypeXX);

Посмотрите на http://code.google.com/p/cloning/

5
ответ дан 8 December 2019 в 03:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: