it-swarm.com.ru

Почему метод clone () защищен в Java.lang.Object?

Какова конкретная причина, по которой clone() определяется как защищенная в Java.lang.Object?

99
Alex N.

Тот факт, что клон защищен, чрезвычайно сомнителен, как и тот факт, что метод clone не объявлен в интерфейсе Cloneable.

Это делает метод довольно бесполезным для получения копий данных, потому что вы не можете сказать :

if(a instanceof Cloneable) {
    copy = ((Cloneable) a).clone();
}

Я думаю, что дизайн Cloneable в настоящее время в значительной степени рассматривается как ошибка (цитата ниже). Обычно я хотел бы иметь возможность создавать реализации интерфейса Cloneable, но не обязательно делать интерфейс Cloneable (аналогично использованию Serializable). Это не может быть сделано без размышления:

ISomething i = ...
if (i instanceof Cloneable) {
   //DAMN! I Need to know about ISomethingImpl! Unless...
   copy = (ISomething) i.getClass().getMethod("clone").invoke(i);
}

Цитата из Эффективная Java Джоша Блоха :
"Интерфейс Cloneable был задуман как смешанный интерфейс для объектов, чтобы объявить, что они разрешают клонирование. К сожалению, он не подходит для этой цели ... Это очень нетипичное использование интерфейсов, а не тот, который нужно эмулировать ... чтобы реализация интерфейса оказала какое-либо влияние на класс, он и все его суперклассы должны подчиняться довольно сложному, неисполнимому и в значительной степени недокументированному протоколу "

97
oxbow_lakes

Интерфейс Clonable - это просто маркер, говорящий, что класс может поддерживать клон. Метод защищен, потому что вы не должны вызывать его для объекта, вы можете (и должны) переопределить его как открытый. 

От солнца:

В классе Object метод clone () объявлен защищенным. Если все, что вы делаете, это реализуете Cloneable, только подклассы и члены одного и того же пакета смогут вызывать clone () для объекта. Чтобы разрешить любому классу в любом пакете доступ к методу clone (), вам придется переопределить его и объявить его общедоступным, как это сделано ниже. (Когда вы переопределяете метод, вы можете сделать его менее закрытым, но не более закрытым. Здесь защищенный метод clone () в Object переопределяется как открытый метод.)

24
Bill K

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

7
Andrew Hare

Метод Clone нельзя напрямую использовать с любым объектом, поэтому он предназначен для переопределения подклассом.

Конечно, это может быть публично и просто выдавать соответствующее исключение, когда клонирование невозможно, но я думаю, что это вводит в заблуждение.

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

4
Silfverstrom

Он защищен, потому что реализация по умолчанию делает поверхностную копию всех полей (включая частные), обходящий конструктор . Это не то, что объект может быть спроектирован для обработки в первую очередь (например, он может отслеживать созданные экземпляры объектов в общем списке или что-то подобное).

По той же причине реализация по умолчанию clone() сгенерирует, если вызываемый объект не реализует Cloneable. Это потенциально небезопасная операция с далеко идущими последствиями, и поэтому автор класса должен явно подтвердить свое согласие.

2
Pavel Minaev

Из ада клонируемого.

* By convention, classes that implement this interface (cloneable) should override 
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link Java.lang.Object#clone()} for details on overriding this
* method.

* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface.  Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.

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

2
Janusz

ИМХО, все так просто:

  • #clone нельзя вызывать для не клонируемых объектов, поэтому он не обнародован
  • #clone должен вызываться подклассами ob Object, которые реализуют Cloneable для получения мелкой копии нужного класса

Какова правильная область для методов, которые должны вызываться подклассами, но не другими классами?

Это protected.

Классы, реализующие Cloneable, конечно, сделают этот метод общедоступным, чтобы его можно было вызывать из других классов.

2
Michaela Elschner

Метод Clone () имеет внутреннюю проверку «экземпляр Cloneable или нет». Именно так, как думала команда Java, будет ограничено неправильное использование метода clone (). Метод clone () защищен, т. Е. Доступен только подклассам. Поскольку объект является родительским классом для всех подклассов, метод Clone () может использоваться всеми классами, если у нас нет проверки «экземпляра Cloneable» выше. По этой причине команда Java могла бы подумать об ограничении неправильного использования clone (), имея проверку в методе clone () «это экземпляр Cloneable».

Следовательно, все классы, реализующие cloneable, могут использовать метод clone () класса Object. 

Кроме того, поскольку он защищен, он доступен только тем подклассам, которые реализуют клонируемый интерфейс. Если мы хотим сделать его общедоступным, этот метод должен быть переопределен подклассом с его собственной реализацией.

0
SARIKA