Я изучал «особые» особенности Java и начал читать клонирование.
Поэтому в настоящее время я понимаю, что клонирование можно использовать для получения идентичной копии объекта. Для этого вы реализуете интерфейс Cloneable и переопределяете метод клонирования Object (что действительно странно для IMO)
Мои вопросы больше относятся к сравнению C ++ и Java. Почему именно отдельный метод клонирования требуется, когда у нас уже есть поддержка конструкторов копирования. Была ли историческая причина того, почему клонирование считалось обязательным?
PS: я не спрашиваю о необходимости «клонировать» как в зачем клонировать объект в Java, я спрашиваю о необходимости Cloneable и метода clone, когда Java уже поддерживает конструкторы копирования.
ИМО твой вопрос состоит из двух частей.
Что нужно для Cloneable интерфейс?
Cloneable интерфейс также известен как интерфейс маркера, это означает, что у него нет никаких методов, его цель — сообщить пользователю этого класса, что он реализует Клон () метод, который унаследован от объекта. Это позволяет выполнить проверку перед вызовом метода clone ():
Animal a = new Dog();
Animal b;
if (a instanceof Cloneable)
b = a.clone();
Это происходит довольно часто в Java; см. например Сериализуемый интерфейс.
Зачем Java нужна Клон () метод вообще, как у него уже есть конструкторы копирования?
Очень короткий ответ полиморфизм. Как бы вы правильно клонировали экземпляр Dog с помощью ссылки на Animal, его суперкласс, если у вас не было Клон () метод?
Клон предназначен для предоставления отдельного экземпляра объекта без уничтожения клонированного. Это довольно полезно (обязательно) в шаблоне прототипа.
Конструктор копирования обычно вызывается в C ++ при передаче по значению (вы также можете использовать его во время конструирования, но обычно он вызывается при передаче объектов через стек либо в качестве параметров, либо в виде возврата). Очень часто первоначальный объект выходит из области видимости.
Вы можете в конечном итоге поменять эти два, если вы действительно хотите пойти на это, но в действительности они служат разным целям, и очень полезно иметь ясность, когда один должен использоваться вместо другого.
Помимо устранения неоднозначности имени, вам нужно подумать о полиморфизме, когда вы хотите клонировать объект из базового указателя.
Конструкторы копирования будут вызываться по типу указателя, а клон (если он виртуальный, как и должно быть) будет вызываться в самой производной реализации.