Должен ли я предоставить глубокий клон при реализации ICloneable? - PullRequest
6 голосов
/ 30 сентября 2008

Из документации MSDN мне неясно, должен ли я предоставлять глубокий или поверхностный клон при реализации ICloneable. Какой предпочтительный вариант?

Ответы [ 3 ]

15 голосов
/ 30 сентября 2008

Краткий ответ: Да.

Длинный ответ: Не используйте ICloneable. Это потому, что .Clone не определяется как мелкий или глубокий клон. Вы должны реализовать свой собственный интерфейс IClone и описать, как должен работать клон.

1 голос
/ 02 января 2014

Учитывая способ определения объекта, не должно быть никаких вопросов о «глубоком клонировании» по сравнению с «мелким клонированием». Если объект инкапсулирует идентичности вещей, клон объекта должен инкапсулировать идентичности тех же вещей. Если объект инкапсулирует значения изменяемых объектов, копия должна инкапсулировать отдельные изменяемые объекты, содержащие одинаковые значения.

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

Если у класса есть поле Foo, которое инкапсулирует состояние List<Bar>, которое должно инкапсулировать тождества объектов в нем, и может в будущем инкапсулировать тождества различных объектов, то клон Foo должен хранить ссылку на новый список, который идентифицирует те же объекты. Если List<Bar> используется для инкапсуляции изменяемых состояний объектов, то клон должен иметь ссылку на новый список, который идентифицирует новые объекты с таким же состоянием.

Если объекты включали отдельные методы «эквивалент» и «равно», с хэш-кодами для каждого, и если для каждого типа объекта кучи существовали ссылочные типы, которые были обозначены как инкапсулирующая идентичность, изменяемое состояние, оба или ни одного, тогда 99% проверки на равенство и методы клонирования могут быть обработаны автоматически. Два агрегата равны, если все компоненты, которые инкапсулируют идентичность или изменяемое состояние, эквивалентны (а не просто равны), и те, которые инкапсулируют ни то, ни другое, по крайней мере равны; два агрегата эквивалентны, только если все соответствующие компоненты являются и всегда будут эквивалентны [это часто подразумевает равенство ссылок, но не всегда]. Копирование агрегата требует создания отдельной копии каждой составляющей, которая инкапсулирует изменяемое состояние, копирования ссылки на каждую составляющую, которая инкапсулирует идентичность, и выполнения любого из вышеперечисленных для тех, которые не содержат ни одну из них; агрегат с компонентом, который инкапсулирует как изменяемое состояние, так и идентичность, не может быть просто клонирован.

Есть несколько хитрых случаев, когда такие правила клонирования, равенства и эквивалентности не будут обрабатываться должным образом, но если бы существовало соглашение, отличающее List<IdentityOfFoo> от List<MutableStateOfFoo> и поддерживающее оба «эквивалента» и тесты «равно», 99% объектов могут иметь автоматически сгенерированные клон, равно, эквивалентно, равноценность и равноценность и работать правильно.

1 голос
/ 30 сентября 2008

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

Редактировать: это соглашение об именах выходит за пределы, то же самое для .Net, Java, C ++, Javascript и т. Д. ... фактический источник находится за пределами моих знаний, но он входит в стандартную объектно-ориентированную лексику, как объекты и классы. Таким образом, MSDN не определяет реализацию, потому что это дано самим словом (конечно, многие новички в ОО-языках этого не знают, и им СЛЕДУЕТ указывать это, но опять же их документация весьма скромна)

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