Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  10:00[Войти] | [Зарегистрироваться]
Ответ на вопрос № 80334

17-11-2011 23:02
Приветствую всех. Академический вопрос: можно ли, имея инициализированную копию объекта, создать его копию?

Поясню. Предположим, имеется простенький класс

TMyClass = class
FInt:Integer;
FStr:string;
FData: TObject;
constructor Create(Int:Integer);
constructor Create(Str:string);
end;

constructor TMyClass.Create(Int:Integer);
begin
FInt:=Int;
FStr:='none';
FData:=TSomeObject.Create(Int);
end;

constructor TMyClass.(Str:string);
begin
FInt:=0;
FStr:=Str;
FData:=TSomeOtherObject.Create(Str+#32);
end;


И пусть у нас на руках есть экземпляр этого класса MyClass, созданный одним из конструкторов. Возможно ли, имея MyClass создать его копию? Напрашивается что-то типа

MyClassCopy := MyClass.ClassType.Create(...);
MyClassCopy.Assign(MyClass);


Однако конструктор вызвать не получится (не знаем аргументов), да и внутри Create создается новый объект...

Быть может как-то при помощи Instance получится? Спасибо.

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

22-11-2011 04:05 | Сообщение от автора вопроса
2 Роман
Спасибо за развернутый комментарий. Совсем без шишек, боюсь, не получится) И тем не менее ваша "простыня" содержит очень полезные сведения.

2 Fisher
TComponent не вариант, увы. Не дерево даже, а несколько. и из общих предков только TInterfacedObject.

Спасибо.

Остановился на полуавтоматическом варианте. Инициализация спец.методом (реализация интерфейса), уничтожение средой.

19-11-2011 11:06
На протяжении 5 лет занимаюсь подобными задачами в САПР.
Рассмотрим задачу о возможности или невозможности размещения некого объекта в абстрактном пространстве,
в котором работает Ваш алгоритм (печатная плата, 2D или 3D пространство, железнодорожные колеи...)

Вот какие проблемы, решаемые программистом, можно классифицировать:
1. Размещение нового объекта;
2. Изменение параметров существующего объекта;
3. Перемещение объекта в другое место пространства;
4. Изменение параметров пространства.

Каждая проблема таит в себе много подводных камней, натыкаясь на которые выработался такой подход:
1. Наследование классов объектов, исходя из принципиальных соображений. С высокой долей вероятности любые объекты в предметной области можно классифицировать, найти общие черты, обобщить и вынести в абстракции все, что только можно. Очень удобно, когда предметный класс отличается от  предка лишь парой перекрытых виртуальных методов и, может, добавленным конструктором;

2. Представте, что для создания нового объекта в рантайме есть диалог, в котором пользователь вводит все-все его параметры. Абсолютно все. Вам нужно придумать, как в этом случае экземпляр будет создаваться. Я знаю такие подходы:
a) Obj := TObjClass.Create; Obj.Prop1 := aProp1; Obj.Prop2 := aProp2;
b) Obj := TObjClass.Create(aProp1, aProp2);
c) Obj := TObjClass.Create(ObjClassParams);

Первый подход имеет право на существование, но его грамотная реализация требует больше организации, потому что свойства ОБЯЗАНЫ проверяться на корректность значений, что на практике может привести к коллизиям: установка корректных свойств по одному может приводить к исключениям, потому что первое свойство требует УЖЕ установленного второго, а оно еще не установлено.

Второй подход требует создание исчерпывающего конструктора для класса. Этот подход очень удобен там, что есть такое место в программе, где ВОЗМОЖНО проверить все данные комплексно и вынести вердикт, можно или нельзя допустить создание объекта с такими параметрами.

Третий подход очень похож на второй, только параметры объекта сгруппированы в спецкласс-держатель этих параметров. С первого взгляда кажется, что это тавтология, но нет. Спецкласс может проверять корректность параметров ДО ВЫЗОВА КОНСТРУКТОРА объекта, который мы хотим создать в итоге. Напомним, что возбуждение исключения в конструкторе объекта - дурной тон, котрый требует в общем случае очень "осторожного" деструктора, который должен все время проверять внутренние поля, которые распределялись в конструкторах, на существование, прежде чем освобождать память.

3. Проверять корректность изменения некого параметра объекта у меня получилось очень легко, используя спецклассы-держатели параметров объектов. Сначала такой объект создается на основе существующего предметного объекта, в него вносится изменение, проверяется корректность существования в таких параметрах обязательно с возвращением кода ошибки. Если таковой не обнаружено, то уже ставим новое значение в сам объект. Этод подход позволяет одновременно изменять НЕСКОЛЬКО ПРОИЗВОЛЬНЫХ СВОЙСТВ сразу.

4. Измение пространства обрабатывается примерно так же: пространство может делать объект "параметры пространства", который детализирован только до необходимого уровня (ничего лишнего, кроме пространства), в который вносятся изменения (в общем случае их может быть сколько угодно). После чего эти "параметры пространства" подаются на проверку с возвратом кода ошибки всем, кто зависит от этого пространства.

5. Используйте методы классов для программирования правил поведения и функций расчета значений по умолчанию для объектов.

Что все это дает? Избавление от стратегии клонирования мучеников для зверских эксперементов; получается, что "все в белом". Здесь на Королевстве проходила мысль о том, чтобы перестать мыслить синглтонами. На практике это значит, что если логика программы изначально не до конца была продумана и пользователь как-то изменяет габарит контейнера на складе, то при требовании заказчика одновременно изменять габарит у произвольного количества этих контейнеров, Вы можете закричать "шеф, усё пропало!!!" :)

Извините за простыню, шишек понабивали много в свое время. Может, хоть кто-то набьет меньше.

19-11-2011 08:17
Теперь понятнее.

Что можно сказать. Если таких объектов - целое развесистое дерево, то, конечно, логично поручить клонирование себя каждому классу. Тогда CloneSelf каждого потомка сможет использовать inherited, а сам должен будет реализовать клонирование только своих потрохов.

Надо помнить, что в методах клонирования, если создавать их "в лоб", "консервируется" структура объекта, так что при доработке объекта нужно внимательно обновлять соответствующие методы клонирования - достаточно тупая и ответственная работа.

При большом объеме данных, неизбежно возникнет идея это все автоматизировать, и тогда вспомним о published-свойствах и RTTI, и припляшем к упоминавшемуся уже TComponent.

Так что, возможно, проще вызвать конструктор.

19-11-2011 07:56 | Сообщение от автора вопроса
Так сравнивать поведение или состояние?
Я вроде бы нигде не упоминал слово "состояние". Извините, если ввел в заблуждение. Поведение конечно. Само по себе — это задача не из простых, кстати.

Повторюсь еще раз о предполагаемом ходе действий.
1. Создается прототип нужного объекта: Prototype := TTestObject.Create(...);
2. Создается клон: Clone := Prototype.CloneSelf;
3. Клон запускается в "песочницу", и там "работает"; вся "работа" логгируется.
4. По окончании работ клон уничтожается.
5. п.п. 2-4 повторяются нужно число раз.

19-11-2011 06:17
Нужно сравнивать поведение произвольного объекта в различных ситуациях

Так сравнивать поведение или состояние?

Ведь два объекта могут исходить из одного и того же исходного состояния, и прийти в другое, тоже равное друг другу, состояние, но при этом идти совершенно разными путями, и по пути творить совершенно разные дела - ведь пользующая сторона может вызывать их методы с разными аргументами.

Тогда сравнение полей двух объектов вначале и в конце ничего не даст. Ведь внутреннее состояние не полностью определяет поведение.

19-11-2011 05:54 | Сообщение от автора вопроса
Да я уже, собственно, и описал возникшую подзадачу. Нужно сравнивать поведение произвольного объекта в различных ситуациях. Без этого — никак. В целом описать проект у меня нет полномочий, да незачем это.

Соответственно появилась мысль о клонировании: создавать экземпляр единожды, делать по мере необходимости копию и подвергать экзекуциям. По завершении — создавать новую копию и т.д. При условии отсутствия зависимости поведения объекта от адреса размещения эта идея смотрелось неплохо. Но увы, как я и предполагал (и как озвучил Void) слишком много неоднозначностей.

Так что сейчас рассматриваю два подхода: либо все-таки заставлять пользователя каждый раз вызывать конструктор, либо обязать исследуемый объект реализовавывать некий интерфейс с функций клонирования (что-то похожее предложил Всеволод).

p.s.:
Задача интересная, нужная и нерешенная никем ранее..
Это я, естественно, не о клонировании/сериализации (что по сути одно и тоже), не об уборке мусора и даже не об озвученной мной задаче анализа поведения объектов. Это о проекте в целом.

19-11-2011 04:11
Конечно, было бы гораздо правильнее привести полную формулировку задачи, которая привела меня к необходимости работы с клонами объектов (в качестве одного из вариантов). Однако в силу многих причин это невозможно.

Перефразируя великого Пьера Ферма, можно только сказать, что у присутствующих, скорее всего, есть прекрасное решение Вашей исходной задачи, но привести здесь его полную формулировку в силу многих причин невозможно.

Практически каждый программист со стажем приходил к идее и клонирования, и сериализации, и ленивой загрузки, и автоматического управления мусором. И хорошо, если вовремя обнаруживал, что он не один в этом мире.

Так что рассказывайте, как дошли до жизни до такой.

18-11-2011 13:31
Наверное, попробую пояснить.

Требуется проследить, как поведет себя достаточно произвольный объект в некоторых условиях.
Окей, создаем:

Obj1:=TObj.Create;


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

Obj2:=TObj.Create;


И вот тут — не факт, что Obj1 и Obj2 совпадают с точностью до полей. Вдруг конструктор опирается на какие-то внешние условия? Сравнивать нельзя. Понятно, что даже клонирование — не панацея, по-хорошему нужно клонировать еще и окружение. Возможность клонировать была бы полезна. Жаль, словом...

18-11-2011 13:24 | Сообщение от автора вопроса
Спасибо.

> Академический интерес - очень стрёмный подход.
Э... я даже не сразу нашелся что ответить... Вроде бы у вас все в порядке с образованием, судя по блогу и публикациям здесь. Не буду навязывать свое виденье, но для новичков оказавшихся здесь поясню, что лично я подразумеваю под "академическим подходом".

Бывает так — перед вами есть задача. Задача интересная, нужная и нерешенная никем ранее (в том смысле, что пока просто никто этим не занимался). И как к ней подступиться, с какого бока подойти к её решению — непонятно. И вот тогда начинается поиск, проба различных подходов... В том числе тех, которые требуют специфических знаний. И тогда есть два пути:

1. Начинать писать код, вырывая с кровью нужные куски из "интернетов", задавая вопросы "а где найти компонент, который решает квадратное уравнение" и т.п. И надеяться, что рано или поздно в результате такого "кодинга" появится на свет программа, решающая поставленную задачу (ну или имеющую видимость этого). Это есть "эмпирический подход", т.е. нахождение решения на практике, путем проб, ошибок и их последовательного исправления (или заворачивания оных в try/except).

2. Подумать, насколько вообще тот или иной подход применим. Немножко копнуть в глубь (возможно под капот языка). Сделать тестовую программу (на несколько порядков проще той, что вам нужна), которая позволит ощутить насколько выбранный подход применим и удобен. И только после этого начинать разработку приложения. Это и есть "академический подход". Хотя он и кажется громоздким и медлительным, на практике при разработке приложения посложнее лабораторных практикумов ВУЗов он оказывается куда как эффективнее.

Соответственно, когда передо мной возникла задача манипуляций с несколькими идентичными (с точностью до значений полей) объектами — я рассмотрел вопрос о возможности клонирования объектов. Как я и отметил в предпоследнем предложении вопроса, таковая возможность сразу же вызывала сомнения. Однако, поскольку я лишь поверхностно знаком с тем как объекты располагаются в памяти — и был задан вопрос, не пропустил ли я чего.

Конечно, было бы гораздо правильнее привести полную формулировку задачи, которая привела меня к необходимости работы с клонами объектов (в качестве одного из вариантов). Однако в силу многих причин это невозможно.

18-11-2011 09:36 | Комментарий к предыдущим ответам
Нужно сказать, что копирование неоднозначная процедура.
+100

@Автор
Академический интерес - очень стрёмный подход. И уважаемый Void на эту тему очень удачно высказался, что я его даже процитировал.

Хочу немного от себя добавить, чуть развивая тему "неоднозначности".
Копирование объекта так или иначе порождает неоднозначность самого объекта.

Что такое, когда у нас в памяти есть два объекта с одинаковым набором полей? Здесь и зарыта "стрёмность". В базах данных это просто запрещено, поэтому разные по размещению записи должны быть уникальны по значению атрибутов (полей). Иначе - кранты.

Объектный подход позволяет сделать разные по размещению объекты с одинаковым набором и значением свойств (данных). Ни к чему хорошему это не приводит. Говоря "академически", видя две ссылки
var
  ref1, ref2 : TMyClass;
в некий момент времени (не будем делать гипотезу, что мы знаем, как система пришла в данное состояние) попробуем-ка понять, глядя на ref1 и ref2 - каким объектам они соответствуют?

Возможные варианты:
- ref1 и ref2 указывают на один объект (одно размещение), т.е. ref1 = ref2
- ref1 и ref2 указывают на разные объекты (в памяти), но у них совпадают поля по значениям

Из второго пункта следует неутешительный вывод, что никто не знает, то ли это в материальном мире существуют 2 одинаковых объекта, то ли был склонирован (скопирован) один и тот же объект.

Единственно, что хоть как-то вносит порядок - разнесение ref1 и ref2 по разным областям жизни. Т.е. клонированный объект должен быть более "локальным", чем исходный.

+ если объекты нужно как-то хранить в базе, то без уникального ID не обойтись.
+ копирование объектов массово снижает производительность приложения
+ если уж и копировать, то точно не встроенными методами, чтобы не ошибиться. если уж это ТАК надо, пусть это будет
    а) труд программиста, что заставит как минимум подумать еще раз
    б) какой-нибудь явный пользовательский метод

Ну и не хочется своим сообщением смазывать главный эффект от предыдущего поста: копирование агрегатов.


17-11-2011 23:27
Встроенных механизмов нет. Классы должны сами уметь себя копировать используя соответствующие методы и/или конструкторы копирования (в VCL этим занимаются методы Assign, AssignTo).
Нужно сказать, что копирование неоднозначная процедура. Например, если класс содержит поле, являющееся указателем на объект - как осуществлять копирование: созданием аналогичного объекта или просто копированием указателя? Компилятор этого не знает, значит это вопрос проектирования класса.

В простейшем случае можно скопировать область памяти, если экземпляры относятся к одному классу, созданы с одним и тем же выравниванием памяти, и в общем случае не содержат ссылок (строк, объектов и т.п.).

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Вода мокрая или сухая?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования