Копирование свойств объекта
От: Chost  
Дата: 12.05.04 11:08
Оценка:
Доброго всем времени суток!

Подскажите как решить проблему, код ниже:
TFirm = class  // созданный класс
  fid       : Word;
  firmname  : String;
end;

procedure TForm.BtnClick(Sender: TObject);
  Var
    FIRM1, FIRM2 : TFIRM;
begin
  FIRM1:=TFirm.Create;
  FIRM2:=TFirm.Create;
  FIRM1.fid:=1;
  FIRM2.fid:=2;

  FIRM1:=FIRM2; // здесь мне нужно скопировать значения всех свойств объекта FIRM2 в FIRM1(в данном случае fid, firmname), а получается что FIRM2 замещает FIRM1.

  FIRM2.Free;
  ShowMessage(IntToStr(FIRM1.fid)); // здесь вместо значения "2" выводится 4096
end;
Re: Копирование свойств объекта
От: Sheridan Россия  
Дата: 12.05.04 11:16
Оценка:
Здравствуйте, Chost,
Простым приравниванием вы просто говрите firm1 чтобы она брала данные из адреса памяти где находится firm2 (на пальцах) соответственно при удалении firm2 удаляются и данные, для приравнивания вы должны приравнять сами данные тоесть надо делать firm1.fid:=firm2.fid либо переопределить оператор = чтобы все это делалось автоматически. Извиняйте на паскале я не знаю как переопределить что либо....
-= ICQ:1887019 =- [Believe in the Matrix...] [...и Winamp молчит...]
Matrix has you...
Re: Копирование свойств объекта
От: AlexEagle Украина http://www.vik.oil
Дата: 12.05.04 11:27
Оценка:
Здравствуйте, Chost, Вы писали:

C> FIRM1:=FIRM2; // здесь мне нужно скопировать значения всех свойств объекта FIRM2 в FIRM1(в данном случае fid, firmname), а получается что FIRM2 замещает FIRM1.


Ну вообще нужно сделать так:

FIRM1.Assign(FIRM2)

...
procedure TFirm.Assign(TFirm firm)
begin
 fid := firm.fid
  .... 
end;



Тогда все будет просто класс
Re[2]: Копирование свойств объекта
От: Chost  
Дата: 12.05.04 11:28
Оценка:
Проблема в том что свойств у меня не 2 а больше, также присутсутсвуют динамические массивы состоящие из объектов(см. ниже)


TFirm = class // созданный класс
  fid      : Word; 
  firmname : String;
  ADDR     : array of TADDR; <------ 
end;
Re: Копирование свойств объекта
От: Spaider Верблюд  
Дата: 12.05.04 11:30
Оценка: 1 (1) +1
Здравствуйте, Chost, Вы писали:

C>Доброго всем времени суток!


C>Подскажите как решить проблему, код ниже:



C> FIRM1:=FIRM2; // здесь мне нужно скопировать значения всех свойств объекта FIRM2 в FIRM1(в данном случае fid, firmname), а получается что FIRM2 замещает FIRM1.


Унаследуй свой класс от TPersistent и используй Assign:

TFirm = class (TPersistent)
  fid : Word;
  firmname : String;
public
  procedure Assign (Source : TPersistent); override;
end;

...

procedure TFirm.Assign (Source : TPersistent); override;
begin
  If Source is TFirm then
    Begin
      fid:=TFirm(Source).fid;
      firmname:=TFirm(Source).firmname;
    end
    else inherited;
end;


И копируй классы вот так:

procedure TForm.BtnClick(Sender: TObject);
Var
 FIRM1, FIRM2 : TFIRM;
begin
FIRM1:=TFirm.Create;
FIRM2:=TFirm.Create;
FIRM1.fid:=1;
FIRM2.fid:=2;

FIRM2.Assign(FIRM1);
FIRM2.Free;
FIRM1.Free;
end;
... << RSDN@Home 1.1.3 stable >>
--
К вашим услугам,
Re[3]: Копирование свойств объекта
От: AlexEagle Украина http://www.vik.oil
Дата: 12.05.04 11:31
Оценка:
Здравствуйте, Chost, Вы писали:

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


Я вроде как написал про функцию Assign которая будет методом этого класса и будет отвечать за присвоение. В ней можно определить какие свойства будут копироваться
Re[2]: Копирование свойств объекта
От: AlexEagle Украина http://www.vik.oil
Дата: 12.05.04 11:35
Оценка:
S>Унаследуй свой класс от TPersistent и используй Assign:

S>
S>TFirm = class (TPersistent)
S>  fid : Word;
S>  firmname : String;
S>public
S>  procedure Assign (Source : TPersistent); override;
S>end;

S>...

S>procedure TFirm.Assign (Source : TPersistent); override;
S>begin
S>  If Source is TFirm then
S>    Begin
S>      fid:=TFirm(Source).fid;
S>      firmname:=TFirm(Source).firmname;
S>    end
S>    else inherited;
S>end;
S>


Что-то я не понимать Зачем тогда унаследовать от TPersistent если все равно самому писать Assign
Re[3]: Копирование свойств объекта
От: Spaider Верблюд  
Дата: 12.05.04 11:44
Оценка:
Здравствуйте, AlexEagle, Вы писали:

S>>Унаследуй свой класс от TPersistent и используй Assign:


AE>Что-то я не понимать Зачем тогда унаследовать от TPersistent если все равно самому писать Assign


Ты бы хоть немножечко хелпик читать

Если у тебя в твоей модели данных всего один класс, то тогда действительно нефиг мудрить. Но такого никогда не бывает

Description
TPersistent encapsulates the behavior common to all objects that can be assigned to other objects, and that can read and write their properties to and from a form file (.xfm or .dfm file). For this purpose TPersistent introduces methods that can be overridden to:

Define the procedure for loading and storing unpublished data to a stream.
Provide the means to assign values to properties.
Provide the means to assign the contents of one object to another.

...


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

И еще, делая именно так ты увеличиваешь читабельность, юзабельность кода и поступаешь в соответствии с общепринятыми правилами. В результате при разработке ты делаешь меньше ошибок.
... << RSDN@Home 1.1.3 stable >>
--
К вашим услугам,
Re[4]: Копирование свойств объекта
От: AlexEagle Украина http://www.vik.oil
Дата: 12.05.04 12:19
Оценка:
Здравствуйте, Spaider, Вы писали:

S>Если у тебя в твоей модели данных всего один класс, то тогда действительно нефиг мудрить. Но такого никогда не бывает


Не знаю, но мне кажется что все сказанное все равно реализуется простым написание своей процедуры Assign, хотя я конечно всега быд сторонником такого кода

procedure TFirm.Assign(TFirm firm); // присвоение фирмы
procedure TFirm.Assign(TUrFace face); // присвоение юр-лица


Такой подход может выявить ошибку в следующем коде атоматически на стадии компиляции:

firm1.Assign(PhisicalFacce) // попытка присвоить физическое лицо фирме - по коду не допустимо


Как по мне (вариант ИМХО) отлавливать ошибки на стадии компиляции — предпочтительней.
Re: Копирование свойств объекта
От: Chost  
Дата: 12.05.04 12:52
Оценка:
Спасибо всем!

Написал функцию Assign и всё заработало отлично!

P.S. Обидно что нет функции FIRM1:=FIRM2 %-)
Re[2]: Копирование свойств объекта
От: Sheridan Россия  
Дата: 12.05.04 12:54
Оценка:
Здравствуйте, Chost, Вы писали:

C>Спасибо всем!


C>Написал функцию Assign и всё заработало отлично!


C>P.S. Обидно что нет функции FIRM1:=FIRM2 %-)

Есть. Только ее тоже надо написать. Тоько я не знаю есть ли это в паскале... на с++ точно можно
-= ICQ:1887019 =- [-=...avanced lamer...=-] [...и Winamp молчит...]
Matrix has you...
Re: Копирование свойств объекта
От: konstbel  
Дата: 13.05.04 14:59
Оценка: 1 (1)
Здравствуйте, Chost,
если унаследовать твои объекты от TObject и объявить их проперти как published, то можно воспользоваться RTTI:
procedure CopyObjectProps(Src, Dst: TObject);
var TypeData: PTypeData;
    Props: PPropList;
    PP: PPropInfo;
    i: integer;
    V: variant;
begin
  TypeData:=GetTypeData(Src.ClassInfo);
  if (TypeData = nil) or (TypeData^.PropCount = 0) then Exit;
  GetMem(Props, TypeData^.PropCount * sizeof(Pointer));
  try
    GetPropInfos(Src.ClassInfo, Props);
    for I := 0 to TypeData^.PropCount-1 do begin
      PP:=GetPropInfo(Dst,Props^[I]^.Name);
      if (PP=nil) then continue; // такого свойства у Dst нет
      V:=GetPropValue(Src,Props^[I]^.Name,false);
      SetPropValue(Dst,Props^[I]^.Name,V);
      end;
  finally
    Freemem(Props);
  end;
end;
Re: Копирование свойств объекта
От: Dimonka Верблюд  
Дата: 13.05.04 15:10
Оценка:
Статья о манипуляции настройками и их сохранении:

http://www.gexperts.com/appsettings1.html
http://www.gexperts.com/appsettings2.html
(английский)
Re[2]: Копирование свойств объекта
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.05.04 04:42
Оценка: +1
Здравствуйте, konstbel, Вы писали:

K>Здравствуйте, Chost,

K>если унаследовать твои объекты от TObject и объявить их проперти как published, то можно воспользоваться RTTI:
Вообще в VCL иногда применяется такой трюк:
компонент сериализуется в TMemoryStream, после чего десериализуется копия. Это чуть-чуть более компактный способ сделать то же самое, что ты предложил.
Нужно только отдавать себе отчет в том, что работоспособность метода опирается на предположение о полноте описания состояния объекта его сериализованным видом. Для компонентов это, как правило, справедливо. Именно из-за того, что разработчик просто обязан обеспечить адекватное представление в dfm. Для произвольного объекта это не всегда так.
... << RSDN@Home 1.1.4 beta 1 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.