Клонирование составных объектов
Существует одна проблема, с которой вам придется столкнуться при реализации глубокого копирования составных объектов. Вы должны предусмотреть выполнение методом clone() глубокого копирования ссылок для составляющих его объектов, а затем, в свою очередь, для ссылок этих объектов и так далее. Это необходимое условие глубокого копирования. Таким образом, вы должны владеть, или по крайней мере, располагать достаточными знаниями о коде всех классов, участвующих в глубоком копировании и быть уверенными в том что их собственные механизмы глубокогокопирования работают безотказно.
Следующий пример показывает последовательность операций для осуществления глубокого копирования составного объекта:
//: Приложение А:DeepCopy.java
// Клонирование составных объектов
class DepthReading implements Cloneable { private double depth; public DepthReading(double depth) { this.depth = depth; } public Object clone() { Object o = null; try { o = super.clone(); } catch(CloneNotSupportedException e) { e.printStackTrace(System.err); } return o; } }
class TemperatureReading implements Cloneable { private long time; private double temperature; public TemperatureReading(double temperature) { time = System.currentTimeMillis(); this.temperature = temperature; } public Object clone() { Object o = null; try { o = super.clone(); } catch(CloneNotSupportedException e) { e.printStackTrace(System.err); } return o; } }
class OceanReading implements Cloneable { private DepthReading depth; private TemperatureReading temperature; public OceanReading(double tdata, double ddata){ temperature = new TemperatureReading(tdata); depth = new DepthReading(ddata); } public Object clone() { OceanReading o = null; try { o = (OceanReading)super.clone(); } catch(CloneNotSupportedException e) { e.printStackTrace(System.err); } // Необходимо клонировать ссылку:
o.depth = (DepthReading)o.depth.clone(); o.temperature = (TemperatureReading)o.temperature.clone(); return o; // Передаем его в Object
} }
public class DeepCopy { public static void main(String[] args) { OceanReading reading = new OceanReading(33.9, 100.5); // Теперь клонируем его:
OceanReading r = (OceanReading)reading.clone(); } } ///:~
Классы DephReading (измерение глубины) и TemperatureReading (измерение температуры) очень похожи, они оба содержат только примитивы. Следовательно и метод clone() для этих классов также предельно прост: он вызывает super.clone() и возвращает результат. Заметьте что код для обоих методов clone() абсолютно идентичен.
OceanReading (исследование океана) состоит из объектов DephReading и TemperatureReading и поэтому, для выполнения глубокого копирования, его метод clone() должен клонировать все ссылки внутри класса OceanReading. Для выполнения этой задачи результат super.clone() должен возвращать ссылку на объект OceanReading (таким образом, вы получите доступ к ссылкам на объекты глубины и температуры).