Трябва ли подкласът изрично да замени метода Clone(), ако суперкласът вече го е направил

Ако клас A разширява клас B и клас B вече има имплементиран интерфейс за клониране, тогава необходимо ли е клас A да декларира 'clone() throws CloneNotSupportedException'.

Предполагам, че не трябва да е задължително, тъй като свойството за клониране на обекти от клас A ще бъде автоматично наследено от клас B.


person Neetigya Jain    schedule 21.10.2010    source източник


Отговори (2)


Необходимо е да се отмени clone(), ако клас B дефинира непримитивни променливи членски полета. Те трябва да бъдат дълбоко копирани изрично в B.clone(). Ако B съдържа само примитивни и/или неизменни членове с данни, A.clone() ще свърши работата.

За по-подробно обяснение вижте този мой по-ранен отговор на подобен въпрос.

person Péter Török    schedule 21.10.2010
comment
Ако извиквате super.clone във всяка реализация на clone, тогава в крайна сметка ще извикате Object#clone. И този метод ще направи плитко копие на всички полета с данни. Мисля, че OP го е разбрала правилно. - person Nikita Rybak; 21.10.2010
comment
@Никита, първата версия на отговора ми наистина беше неправилна, но оттогава я актуализирах и сега вярвам, че е правилна. - person Péter Török; 21.10.2010
comment
Ако някой от предците на B дефинира clone по отношение на конструктор за копиране, а не по отношение на Object, тогава B трябва да направи същото. Ако B използва конструктор за копиране, въпреки че всички негови предшественици са верижни към base.clone, той принуждава всички негови потомци също да използват конструктор за копиране. Лично аз намирам за досадна идеята за методи за клониране, които правят нещо различно от свързване към base.clone, но уви такива методи са много често срещани. - person supercat; 18.01.2012

Ако родителският клас и всички предшественици имплементират своя Clone метод, като извикват Clone метода на своя родителски клас, чак до Object.clone, и ако нито едно от полетата, добавени от подкласа, не съдържа препратки към неща, които трябва да могат да се променят на един обект без да засяга другия, тогава човек може просто да наследи клонинг, без да го отменя. Ако родителският клас прилага метода за клониране, както е описано по-горе, но подкласът добавя полета, които сами трябва да бъдат клонирани, най-добрият модел е подкласът да извика base.Clone и след това да клонира съответните полета.

Ако родителският клас или който и да е предшественик не имплементира своя Clone метод, както е описано по-горе, а вместо това използва конструктор за копиране, тогава производният клас и всички базови класове, извлечени от него) трябва да заменят Clone, за да направят същото, независимо дали базовият клас добавя всякакви нови полета.

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

person supercat    schedule 18.12.2011