Философия Java


Управление клонируемостью объектов - часть 4


Класс WrongClone иллюстрирует неправильную реализацию наследования клонирования. В нем метод Object.clone() переопределяется как public, но не реализован интерфейс Cloneable, поэтому вызов super.clone() (в результате которого вызывается Object.clone()) приводит к возникновению исключительной ситуации CloneNotSupportedException и клонирование не выполняется.

В классе IsCloneable клонирование реализовано правильно: метод clone() переопределяется и реализуется интерфейс Cloneable. Однако, метод clone(), а также некоторые другие методы в этом примере не перехватывают исключительную ситуацию CloneNotSupportException, а лишь возвращают ее вызвавшему методу, где должна быть предусмотрена обработка в блоке операторов try-catch. Вам скорее всего придется обрабатывать эту ситуацию внутри вашего метода clone() гораздо чаще чем просто передавать ее, но в качестве примера гораздо информативнее было ограничиться лишь передачей.

В классе NoMore предпринята попытка отключения клонирования способом, рекомендуемым разработчиками Java: в методе clone() класса-наследника генерируется исключительная ситуация CloneNotSupportedException. В методе clone() класса TryMore как и положено вызывается метод super.clone(), который таким образом приводит к вызову метода NoMore.clone(), который генерирует исключительную ситуацию и предотвращает клонирование.

Но что если программист не станет следовать "правильной" схеме вызова метода super.clone() в переопределенном методе clone()? На примере класса BackOn вы можете наблюдать пример таких действий. Этот класс использует специальный метод duplicate() для копирования текущего объекта и в clone() вызывает этот метод вместо вызова super.clone(). При этом исключительная ситуация не генерируется и класс может быть клонирован. Это пример того, что нельзя рассчитывать на генерацию исключительной ситуации как на защиту класса от клонирования. Единственный верный способ для этого, показан на примере класса ReallyNoMore где класс описан как завершенный (final), то есть как класс, который не может быть наследован. Это означает что если метод clone() генерирует исключительную ситуацию в final классе, то ее не удасться обойти при помощи наследования, что обеспечивает гарантированную защиту от клонирования (вы не можете явно вызвать Object.clone() из класса с произвольным уровнем наследования; можно вызвать лишь метод super.clone(), через который будет произведено обращение к методу базового класса). таким образом, разрабатывая объекты с высоким уровнем защиты, такие классы лучше описывать как final.




Начало  Назад  Вперед



Книжный магазин