Правильное клонирование требует использования виртуального метода, который реализован на самом низком уровне, который поддерживает клонирование, и - в зависимости от того, как клонирование реализовано - либо переопределяется каждым уровнем, чем тот, который добавляет новые поля, которые требуютглубокое клонирование или переопределяется каждым производным классом, точка.
Если все реализации clone
работали, вызывая super.clone
до точки, где класс самого низкого уровня вызывает object.clone
, затем вызываяclone
для производного типа, который был приведен к базовому типу, даст объект этого производного типа.К сожалению, вера в то, что super.clone
не работает, привела к тому, что многие люди используют конструкторы копирования вместо вызова super.clone
, создавая, таким образом, неудачное самоисполняющееся пророчество.
Учитывая эту неудачную ситуацию, лучшее, что можно сделатьвероятно, что каждый класс, чей родительский объект предоставляет метод clone
, который может не связываться с object.clone
, предоставляет конструктор копирования protected
, который принимает экземпляр своего типа, цепочки к конструктору копирования родительского класса, копирует все добавленные поляэтим производным типом, который публично предоставляется (или отображается на свойства, которые являются) или ссылаются на неизменяемые объекты, и клонирует любые поля этого производного типа, которые не являются публично доступными, и ссылаются на изменяемые объекты.Этот подход будет работать, но для каждого класса, производного от клонируемого класса, будет необходимо реализовать свое собственное переопределение метода виртуального клона, даже если единственное, что делает этот метод, - это вызывает конструктор защищенной копии своего собственного класса.
Если ваш родительский класс имеет не виртуальный метод клонирования, который вызывает какой-либо конструктор без виртуальной диспетчеризации, то невозможно правильно реализовать какой-либо производный класс.