русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Клонирование


Дата добавления: 2015-06-12; просмотров: 740; Нарушение авторских прав


Механизм клонирования, как следует из названия, позволяет по­рождать новые объекты на основе существующего, которые обладали бы точно таким же состоянием, что и исходный. То есть ожидается, что для исходного объекта, представленного ссылкой х, и результата клонирова­ния, возвращаемого методом х.clone(), выражение

X != x.cloneO

должно быть истинным, как и выражение

x.clone().getClass() == x.getClass()

Наконец, выражение

x.equals(x.clone())

также верно. Реализация такого метода clone() осложняется целым рядом потенциальных проблем, например:

• класс, от которого порожден объект, может иметь разнообразные конструкторы, которые к тому же могут быть недоступны (напри­мер, модификатор доступа private);

• цепочка наследования, которой принадлежит исходный класс, может быть довольно длинной, и каждый родительский класс мо­жет иметь свои поля — недоступные, но важные для воссоздания состояния исходного объекта;

• в зависимости от логики реализации возможна ситуация, когда не все поля должны копироваться для корректного клонирования; одни могут оказаться лишними, другие потребуют дополнитель­ных вычислений или преобразований;

• возможна ситуация, когда объект нельзя клонировать, дабы не на­рушить целостность системы.

Поэтому было реализовано следующее решение.

Класс Object содержит метод clone(). Рассмотрим его объявление:

protected native Object clone() throws CloneNotSupportedException;

Именно OH используется для клонирования. Далее возможны два варианта.

Первый вариант: разработчик может в своем классе переопределить этот метод и реализовать его по своему усмотрению, решая перечисленные проблемы так, как того требует логика разрабатываемой системы. Упомянутые условия, которые должны быть истинными для клонированного объекта, не являются обязательными и программист может им не следо­вать, если это требуется для его класса.



Второй вариант предполагает использование реализации метода clone() в самом классе Object. То, что он объявлен как native, говорит о 'KW, что его реализация предоставляется виртуальной машиной. Естест­венно, перечисленные трудности легко могут быть преодолены самой JVM, ведь она хранит в памяти все свойства объектов.

При выполнении метода clone() сначала проверяется, можно ли клонировать исходный объект. Если разработчик хочет сделать объект своего класса доступными для клонирования черезObject.clone(), и он должен реализовать в своем классе интерфейс Cloneable. В этом интерфейсе нет ни одного элемента, он служит лишь признаком для виртуальной машины, что объекты могут быть клонированы. Если проверка не выполняется успешно, метод порождает ошибку NoneNotSupportedException.

Если интерфейс Cloneable реализован, то порождается новый объект того же класса, от которого был создан исходный объект. При этом программирование выполняется на уровне виртуальной машины, никакие конструкторы не вызываются. Затем значения всех полей, объявленных, унаследованных либо объявленных в родительских классах, копируют полученный объект возвращается в качестве клона.

Обратите внимание, что сам класс Object не реализует интерфейс Cloneable, а потому попытка вызова new Object().clone() будет приводит, к ошибке времени исполнения. Метод с1опе{) предназначен скорее iL> использования в наследниках, которые могут обращаться к нему с помощью выражения super.clone(). При этом могут быть сделаны следующие изменения:

• модификатор доступа расширен до public;

• удалено предупреждение об ошибке CloneNotSupportedException

• результирующий объект может быть модифицирован любым способом, на усмотрение разработчика.

Напомним, что все массивы реализуют интерфейс Cloneable и, та­ким образом, доступны для клонирования.

Важно помнить, что все поля клонированного объекта приравнива­ются, их значения никогда не клонируются. Рассмотрим пример:

public class Test implements Cloneable { Point p; int height;

public Test(int x, Int y, int z) {

p=new Point(x, y);

height=z; }

public static void main{String s[]) { Testt1=newTest(1, 2, 3), t2; try{

t2=(Test)t1.clone(); } catch {CloneNotSupportedException e) {} t1.p.x=-1; t1.height=-1;

System.out.println("t2.p.x=" + t2.p.x + ", t2.height=" +12. height); } }

Результатом работы программы будет; t2.p.x=-1,t2.helght=3

Из примера видно, что примитивное поле было скопировано и далее существует независимо в исходном и клонированном объектах. Изменение одного не сказывается на другом.

А вот ссылочное поле было скопировано по ссылке, оба объекта ссы­лаются на один и тот же экземпляр класса Point. Поэтому изменения, происходящие с исходным объектом, сказываются на клонированном.

Этого можно избежать, если переопределить метод clone() в классе Test.

public Object clone() { Testclone=null; try{

clone=(Test) super.clone(); } catch (CloneNotSupportedException e) {

throw new lnternalError(e.getMessage());

}

clone.p=(Point)clone.p.clone(); return clone; }

Обратите внимание, что результат метода Object.clone() приходится явно приводить к типу Test, хотя его реализация гарантирует, что клониро­ванный объект будет порожден именно от этого класса. Однако тип возвра­щаемого значения в данном методе для универсальности объявлен как Object, поэтому явное сужение необходимо.

Теперь метод main можно упростить:

public static void main(String s[]) {

Test t1 =new Test( 1, 2, 3);

Test t2=(Test)t1 .CloneO;

t1.p.x=-1;

t1.height=-1;

System.out.println("t2.p.x=" + t2.p.x + ", t2.helght=" + t2.height); }

Результатом будет:

t2.p.x=1,t2.height=3

To есть теперь все поля исходного и клонированного объектов стали независимыми.

Реализация такого "неглубокого" клонирования в методе 4ect.clone() необходима, так как в противном случае клонирование второстепенного объекта могло бы привести к огромным затратам ресурсов, ведь этот объект может содержать ссылки на более значимые объекты, а тс при клонировании также начали бы копировать свои поля, и так далее. Кроме того, типом поля клонируемого объекта может быть класс, не реализующий Cloneable, что приводило бы к дополнительным проблемам. Как показано в примере, при необходимости дополнительное копирование можно добавить самостоятельно.



<== предыдущая лекция | следующая лекция ==>
Переменные типа массив и их значения | Клонирование массивов


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 1.496 сек.