Форум: "Потрепаться";
Текущий архив: 2003.06.02;
Скачать: [xml.tar.bz2];
ВнизРабота с объектами Найти похожие ветки
← →
J_S (2003-05-15 12:34) [0]Можно ли как-нибудь обойти передачу обьектов по ссылке?
← →
MBo (2003-05-15 12:42) [1]Уточни задачу.
Не устраивает, что в процедуре можно с переданным объектом вытворять, что угодно?
← →
uw (2003-05-15 12:42) [2]А в чем надобность?
Строго, по ссылке - это так:
procedure aaa(var Obj: TObject);
а по значению: procedure aaa(Obj: TObject);
Речь-то о чем-то другом?
← →
J_S (2003-05-15 12:48) [3]хотелось бы внутри процедуры запомнить состояние глобального обьекта на момент входа в процедуру
простое переприсваивание - передача по ссылке, а переписывать вручную все свойства глобального обьекта во временный конечно можно,но...как-то не нравицца мне такой метод
← →
MBo (2003-05-15 12:51) [4]Если это наследник TPersistent, то реализовать и применять Assign.
← →
J_S (2003-05-15 12:54) [5]подробнее можно?
← →
MBo (2003-05-15 13:00) [6]у объектов, являющихся потомками TPersistent, имеется метод Assign, предназначенный для "глубокого копирования".
В самом TPersistent он абстрактный, так что у наследникоа этого класса или других с нереализованным Assign нужно перекрыть этот метод, копируя каждое поле объекта. Если делается наследник от класса ,в котором Assign работающий, нужно вызвать inherited, затем скопировать нововведенные поля. Надо не забывать об аккуратной работе с указательными и списочными полями.
← →
Digitman (2003-05-15 13:09) [7]
> J_S
Обойти нельзя.
В случае с рекомендацией MBo © (15.05.03 12:51) в процедуре необходимо будет создать отдельный экз-р того же класса и назначить ему свойства, которые будут передаваться параметром в процедуру (в том или ином виде) из вызывающего кода.
Иными словами, вызывающий код считывает свойства объекта-оригинала (того самого, к которому в теле процедуры не должно быть непоср.доступа), формирует некую структуру (перечисляющую эти св-ва) и вызывает пройедуру. передавая ей эту структуру. Вызванная процедура, получив параметром эту структуру, создает свой собственный экз-р объекта и назначает ему св-ва, которые считывает из переданной структуры в заранее оговоренном порядке/формате. Далее вызванная процедура уже работает с точной копией оригинала.
← →
Mystic (2003-05-15 13:21) [8]
type
TMyClass = class(TPersistent)
private
FA1: Integer;
FA2: string;
public
procedure Assign(Source: TPersistent); override;
published
property A1: Integer read FA1 write FA1;
property A2: string read FA2 write FA2;
end;
procedure TMyClass.Assign(Source: TPersistent);
var
MyClass: TMyClass;
begin
if Sourse is TMyClass then
begin
MyClass := Source as TMyClass;
FA1 := MyClass.A1;
FA2 := MyClass.A2;
end
else
inherited Assign(Source);
end;
// Ниже
var
Orig: TMyClass;
procedure Test;
var
NewClass: TMyClass;
begin
NewClass := TMyClass.Create;
try
NewClass.Assign(Orig);
if RunEdit(NewClass) then Orig.Assign(NewClass);
finally
NewClass.Free;
end;
end;
← →
J_S (2003-05-15 13:34) [9]большой сенькс всем- щаз запробуем:))..
← →
passm (2003-05-15 15:04) [10]Про AssignTo забыли.
← →
Юрий Зотов (2003-05-15 15:06) [11]> passm © (15.05.03 15:04)
Странно...
И что же именно забыто про AssignTo?
← →
VaS (2003-05-15 15:55) [12]Юрий Зотов: Видимо, товащь имел в виду более правильным перекрытие AssignTo(), нежели Assign(). Я с ним целиком и полность соглашусь. Почему - см. Assign() и TPersistent.
← →
Юрий Зотов (2003-05-15 16:19) [13]> VaS © (15.05.03 15:55)
TPersistent (включая Assign) я знаю наизусть (по крайней мере, в D1-D5), так что смотреть нет необходимости. Тем не менее, не вижу причин, почему лучше перекрывать именно AssignTo, а не Assign. Было бы интересно узнать Ваше мнение.
← →
MBo (2003-05-15 16:27) [14]Видимо, имелось в виду, что Assign использует AssignTo?
← →
Юрий Зотов (2003-05-15 16:43) [15]Возможно. Ну так и что с того? Непонятно. Но действительно интересно.
← →
J_S (2003-05-15 16:46) [16]Хотите сказать это есть принципиальный вопрос производительности метода? Или так более правильно с архитектурной точки зрения?
← →
Suntechnic (2003-05-15 16:47) [17]>passm ©
Не надо путать котлеты с мухами.
Если объектA
знает как скопировать данные в объектВ
то Assign-а вполне достаточно. Если, вдруг, оказывается, чтоA
понятия не имеет что такоеВ
, то логично предположить, чтоВ
знает что такоеA
. Вот здесь и работает AssignTo.
← →
DiamondShark (2003-05-15 17:30) [18]Да и вообще, может оказаться, что раз какой-то объект сделан глобальным, то создавать его дополнительные копии не только не имеет смысла, но и просто невозможно.
← →
Mystic (2003-05-15 18:10) [19]
procedure AssignTo(Dest: TPersistent); virtual;
procedure Assign(Source: TPersistent); virtual;
procedure TPersistent.AssignTo(Dest: TPersistent);
begin
Dest.AssignError(Self);
end;
procedure TPersistent.Assign(Source: TPersistent);
begin
if Source <> nil then Source.AssignTo(Self) else AssignError(nil);
end;
Да, наверное более правильно перекрыть AssignTo, поскольку вызов Assign по умолчанию сводится к вызову AssignTo, но не наоборот. но что-то меня не повидает чувство, что раньше было с точностью до наоборот (более того, метод AssignTo был статическим). Или это был сон?
← →
J_S (2003-05-15 18:28) [20]2 DiamondShark
вообщем-то создать копию обьекта не являецца самоцелью, цель - запомнить состояние объекта перед изименениями - другого выхода кроме как кланировать его я не нашла - буду весьма признательна, если предложите другой вариант.
>Да, наверное более правильно перекрыть AssignTo, поскольку вызов Assign по умолчанию сводится к вызову AssignTo
так все-таки.. какой метод лучше перекрывать вызываемый(AssignTo) или вызывающий (Assign)?
← →
Suntechnic (2003-05-15 18:45) [21]>Да, наверное более правильно перекрыть AssignTo, поскольку вызов Assign по умолчанию сводится к вызову AssignTo
Ну вы даёте ребята. Дык по умолчанию он сводится к вызову AssignTo только потому, что когда в Borland реализовывали TPersistent они понятия не имели чего мы тут с вами будем ваять.
>J_S ©
так все-таки.. какой метод лучше перекрывать вызываемый(AssignTo) или вызывающий (Assign)?
Перекрывать надо Assign. А вот если внутри Assign выясниться, что объект который нам передали нам неизвестен, тогда вызываем inherited.Assign который в свою очередь вызывает AssignTo. Т.е. мы предполагаем, что коль нам неизвестно что нам передали, то, может, тому, что нам передали, известно кто такие мы. Вообщем перечитай ещё раз Suntechnic © (15.05.03 16:47) чтобы понять логику.
← →
Юрий Зотов (2003-05-15 19:50) [22]ПРАВИЛЬНО делать так.
Правило 1.
Перекрываем Assign для копирования экземпляра СВОЕГО же класса (и ТОЛЬКО своего) в себя.
Правило 2. Если наш класс должен уметь копировать себя (полностью или частично) еще и в ДРУГИЕ классы (из других веток наследования), то для этого (и ТОЛЬКО для этого) перекрываем AssignTo.
В чем смысл этих правил и как они работают?
Вот стандартное перекрытие Assign (при условии, что TMyClass напрямую унаследован от TPersistent, иначе могут быть нюансы):
procedure TMyClass.Assign(Source: TPersistent);
begin
if Source is TMyClass then
with TMyClass(Source) do
begin
... // копирование Source в себя
end
else inherited
end;
А вот стандартное перекрытие AssignTo (при том же условии, что TSomeClass напрямую унаследован от TPersistent, иначе тоже могут быть нюансы):
procedure TSomeClass.AssignTo(Dest: TPersistent);
begin
if Dest is TFriendClass then
with TFriendClass(Dest) do
begin
... // копирование себя в Dest
end
else inherited
end;
Смысл этого сводится к следующему.
Положим, я пишу класс TMyClass. Естественно, про него я знаю абсолютно все, поэтому если (Source is TMyClass), то в Assign я правильно копирую все, что требуется моему классу (правило 1). Цель достигнута.
Если же Source НЕ является TMyClass"ом, то я понятия не имею, что это за Source такой, кто и когда его написал и откуда он вообще взялся. Возможно, он знает про мой TMyClass и сам умеет с ним работать, а возможно и нет. Тогда в своем Assign я вызываю унаследованный Assign, а тот вызывает Source.AssignTo. Если Source умеет работать с моим TMyClass"ом (то есть, в нем перекрыт AssignTo и TMyClass для него является TFriendClass"ом), то он сам все правильно скопирует (см. правило 2) - и в этом случае цель тоже будет достигнута. А если Source НЕ умеет работать с моим TMyClass"ом, то цели достичь невозможно - и, независимо от того, перекрыт ли AssignTo в Source, или нет, мы получим совершенно логичное исключение.
Вот и все. Borland, как всегда, сделала просто и красиво.
← →
Mystic (2003-05-15 19:53) [23]Смысл такой: если мы разрабатываем класс TA и нам надо реализовать присваивание TA := TB, то надо перекрывать Assign, если нам надо реализовать TB := TA, то надо перекрыть AssignTo. А для реализации TA := TA можно перекрыть любой из методов, только если перекрыть Assign, то вызов AssignTo с этими классами работать не будет.
Страницы: 1 вся ветка
Форум: "Потрепаться";
Текущий архив: 2003.06.02;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.008 c