Чтобы понять различие, нужно сначала понять, что такое ссылка на объект. Поскольку термин «ссылка» используется для обозначения ряда различных понятий, мне нравится термин «Идентификатор объекта». Чтобы использовать автомобильную аналогию, идентификатором объекта является лист бумаги с VIN-кодом автомобиля. Если вы передадите в магазин краски лист бумаги с надписью «VIN ZX357» и попросите магазин покрасить его в синий цвет, магазин не покрасит листок бумаги в синий, а скорее найдет автомобиль с этим номером VIN. и покрасить эту машину в синий.
Если у вас есть переменная Wuzzle
типа Car
(которая является ссылочным типом), которая содержит VIN ZX357, и другая переменная Fuzzle
, и одна говорит Fuzzle = Wuzzle
, тогда Fuzzle
будет - like Wuzzle
удерживайте "VIN ZX357". Там еще будет одна машина. У одного будут только две бумажки, каждая из которых содержит один и тот же VIN и, следовательно, относится к одной и той же машине. Заявление типа Wuzzle.Color=Purple
приведет к тому, что автомобиль с VIN ZX357 будет окрашен в фиолетовый цвет Запрос на проверку Fuzzle.Color
будет смотреть на автомобиль ZX357 и сообщать, что он фиолетовый.
Если вместо того, чтобы сказать Fuzzle = Wuzzle
, кто-то сказал Fuzzle = (Car)(Wuzzle.Clone())
, эффект будет состоять в том, чтобы создать новый автомобиль, который будет похож на VIN ZX357, за исключением того, что у него будет другой номер VIN (например, QL793) и * 1015. * будет содержать новый VIN, а не 3941QXY5). Сказав Wuzzle.Color = Orange
, можно покрасить автомобиль 3941QXY5 в оранжевый цвет, но это не повлияет на автомобиль QL793.
Переменные типа интерфейса обрабатываются так же, как и любой другой ссылочный тип. Можно заменить IColorizable
на Car
, и поведение будет точно таким же.
Важно отметить, что ICloneable
не очень хороший интерфейс; гораздо лучший интерфейс - ICloneable<T>
, который возвращает объект типа T
. У этого интерфейса есть два больших преимущества:
- С
ICloneable
необходимо типизировать тип возвращаемого значения к типу объекта, который вы хотите. Это немного некрасиво. ICloneable<T>
устраняет это требование.
- С
ICloneable
может быть некоторая неоднозначность относительно того, какие ссылки на объекты внутри объекта должны быть скопированы в клон как есть, а какие должны быть клонированы сами. Неоднозначность не так плоха, как это делают некоторые люди, но обобщенный ICloneable<T>
может сделать ее немного понятнее. Например, если у кого-то есть объект CloneableSortedList<T>
, то вызов ICloneable<CloneableSortedList<T>.Clone()
в этом списке должен вернуть новый CloneableSortedList
, который содержит те же ссылки на тип T, что и исходный. Напротив, если у вас есть CloneableSortedUserList
, вызов ICloneable<CloneableSortedUserList>
должен вернуть новый CloneableSortedUserList
, который будет рассматривать атрибуты пользователей, а не ссылки на объекты пользователя, как значения (таким образом, копируя их, если они изменчивы).