Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.11.28;
Скачать: CL | DM;

Вниз

Копирование значений свойств из одного объекта в другой   Найти похожие ветки 

 
Unknown user ©   (2004-11-12 10:48) [0]

Как скопировать значения всех public и published свойств из объекта A в объект B, не вызывая при этом методы Set..., а записывая значения непосредственно в поля. Объекты одного класса. Решения вида B.FProp1:=A.Prop1 не предлагать.


 
Digitman ©   (2004-11-12 11:13) [1]

общего решения не существует.

именно поэтому разработчики, отчетливо понимающее это, при копировании объектов в конечном итоге используют именно последовательность вызовов B.PropN:=A.PropN (в том или ином виде)

и только не говори что у тебя "частный" случай : был бы частный, ты бы сподобился привести конкретную декларацию и реализацию класса.


 
PVOzerski ©   (2004-11-12 11:14) [2]

Писать объекты так, чтобы все свойства были "завязаны" на переменные, а не на методы. И переменные эти были видимыми извне (если речь идет о разных юнитах). Ну, а то, что такое решение в большинстве случаев мало полезно - это уже вопрос другой. Объясняю: при компиляции выражения вроде B.FProp1:=A.Prop1 преобразаются в обращения к соответствующим полям или методам.


 
Digitman ©   (2004-11-12 11:27) [3]


> Unknown user ©   (12.11.04 10:48)  


> public и published


судя по присутствию этих секций в декларации класса, она будет фигурировать у тебя в интерфейсном разделе модуля.

это означает потенциальную возможность реализации наследников этого класса, что в свою очередь никак не ограничивает возможность пополнения экз-ра класса-наследника новыми свойствами, не присутствующими в предке .. и эти св-ва, возможно, реализованы не просто полями, как это выглядит в предке, а уже Get/Set-методами ..

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


 
Vlchel   (2004-11-12 11:31) [4]

Нормально в VCL это реализуется методом Assign. Он объявлен в классе TPersistent


 
Digitman ©   (2004-11-12 11:42) [5]


> Vlchel   (12.11.04 11:31) [4]


чего реализуется-то ?) ничего им не реализуется..
ну вызвал кто-то B.Assign(A), ну вызовет А в свою очередь в ответ на это виртуальный AssignTo(B) и за сим успокоится ..

а AssignTo()-то кто будет перекрывать (и реализовывать там все то самое, о чем здесь базар собссно и идет) ? снова бедный Пушкин ?


 
Vlchel   (2004-11-12 12:29) [6]

Конечно реализовывать свой код можно только своими руками


 
Unknown user ©   (2004-11-12 12:59) [7]

Объясню как я до такого докатился. Возникла у меня необходимость в объектах, содержащих в себе свойства нескольких объектов такого-же класса, при этом естественно такой объект может нести в себе только совпадающие по значению свойства всех объединенных в себе объектов, а несовподающие свойства должны быть помечены как неопределенные. Пример такого объекта Selection.Font в MS Word. Создал общий для всех объектов класс


TCommonObj=class(TPersistent)
 private
  FChangedProps,
  FUndefinedProps:TList;
  FNotifyed:TCommonObj;
 protected
  procedure Changed(Sender:TObject); virtual;
  procedure ChangedProp(AProp:string);
  procedure AfterAssign(Sender:TObject); virtual;
  function GetPropList(AClass:TClass; var PropCount:integer):PPropList;
  procedure AddToChangedProp(PropName:string);
  procedure AddToUndefinedProp(PropName:string);
  procedure AddAllPropsToChanged;
  procedure AddAllPropsToUndefined;
  procedure ClearChangedProps;
  procedure ClearUndefinedProps;
  function GetCommonClass(Obj1,Obj2:TCommonObj):TClass;
  procedure CopyChangedPropsTo(Dest:TCommonObj);
  procedure CompareWith(AObj:TCommonObj);
 public
  constructor Create(ANotifyed:TCommonObj); virtual;
  destructor Destroy; override;
  function IsChangedProp(PropName:string):boolean;
  function IsUndefinedProp(PropName:string):boolean;
end;

//******************************************************************************
function TCommonObj.GetCommonClass(Obj1,Obj2:TCommonObj):TClass;
begin

if Obj1.ClassType=Obj2.ClassType
 then Result:=Obj1.ClassType
 else
if Obj1.InheritsFrom(Obj2.ClassType)
 then Result:=Obj2.ClassType
 else
if Obj2.InheritsFrom(Obj1.ClassType)
 then Result:=Obj1.ClassType
 else begin
  Result:=Obj2.ClassParent;
  while not Obj1.InheritsFrom(Result) do
   Result:=Result.ClassParent;
end;
end;

//******************************************************************************
procedure TCommonObj.CopyChangedPropsTo(Dest:TCommonObj);
var ComClass:TClass;
   PropList:PPropList;
   P:PPropInfo;
   Vl:Variant;
   Ind,PropCount:integer;
begin

if FChangedProps.Count=0 then exit;

ComClass:=GetCommonClass(Self,Dest);
PropList:=GetPropList(ComClass,PropCount);
try
 for Ind:=0 to PropCount-1 do
  if FChangedProps.IndexOf(PropList[Ind])>=0 then begin
   P:=PPropInfo(PropList[Ind]);
   Vl:=GetPropValue(Self,P.Name);
   if P.PropType^^.Kind=tkSet then
    if VarType(Vl)=varInteger then
     SetOrdProp(Dest,P,Vl) else
    if VarToStr(Vl)<>"" then
     SetSetProp(Dest,P,VarToStr(Vl))
    else SetOrdProp(Dest,P,0)
   else SetPropValue(Dest,P.Name,Vl);
  end; {if}
finally
 FreeMem(PropList);
end;

end;

//******************************************************************************
procedure TCommonObj.CompareWith(AObj:TCommonObj);
var ComClass:TClass;
   PropList:PPropList;
   Ind,PropCount:integer;
   S:string;
   Vl1,Vl2:Variant;
begin

ComClass:=GetCommonClass(Self,AObj);
PropList:=GetPropList(ComClass,PropCount);
try
 for Ind:=0 to PropCount-1 do
  if PropList[Ind]^.PropType^.Kind<>tkMethod then begin
   S:=PropList[Ind]^.Name;
   Vl1:=GetPropValue(Self,S);
   Vl2:=GetPropValue(AObj,S);
   if (Vl1<>Null) and (Vl2<>Null) and (Vl1<>Vl2)
    then AddToUndefinedProp(S);
  end; {if}
finally
 FreeMem(PropList);
end;

end;

//******************************************************************************
procedure TCommonObj.AddToChangedProp(PropName:string);
var P:PPropInfo;
begin
P:=GetPropInfo(PTypeInfo(Self.ClassInfo),PropName);
if (P<>nil) and (FChangedProps.IndexOf(P)<0)
 then FChangedProps.Add(P);
end;

//******************************************************************************
procedure TCommonObj.AddToUndefinedProp(PropName:string);
var P:PPropInfo;
begin
P:=GetPropInfo(PTypeInfo(Self.ClassInfo),PropName);
if (P<>nil) and (FUndefinedProps.IndexOf(P)<0)
 then FUndefinedProps.Add(P);
end;

//******************************************************************************
function TCommonObj.IsChangedProp(PropName:string):boolean;
var P:PPropInfo;
begin
Result:=false;
P:=GetPropInfo(Self,PropName);
if P<>nil then Result:=FChangedProps.IndexOf(P)>=0;
end;

//******************************************************************************
function TCommonObj.IsUndefinedProp(PropName:string):boolean;
var P:PPropInfo;
begin
Result:=false;
P:=GetPropInfo(Self,PropName);
if P<>nil
 then Result:=FUndefinedProps.IndexOf(P)>=0;
end;



Где в списке FUndefinedProps хранятся ссылки на свойства, значения которых неопределлено.
При вызове Assign потомками TCommonObj копировать надо значения только тех свойств которые определенны, а постоянно вызывать IsUndefinedProp("PropName") не хочется. Неплохо бы использовать SePropValue, но эта процедура вызывает SetProc свойства, что в Assign недопустимо.

Подскажите еще варианты...


 
Digitman ©   (2004-11-12 13:26) [8]


> Unknown user ©   (12.11.04 12:59) [7]


что-то какую-то жуткую кашу ты заварил, мне кажется ..

скажи, а зачем объекту знать о тек.значениях свойствах других своих "родственников" ?

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


 
Unknown user ©   (2004-11-12 15:02) [9]

2 Digitman. Да. Но не только установить значения свойств, но и считать их. Был бы вариант попроще, я бы конечно такую кашу не заварил. Вся проблема в этих самых неопределенных значениях мульти-объекта. В MS Word для обозначения того что свойство не определенно используется константа wdUndefined. Но как там построены классы я не знаю, и как подобное реализовать в Паскале тоже не знаю. Пришлось изобретать такой вот жуткий велосипед...


 
Digitman ©   (2004-11-12 15:15) [10]


> Unknown user ©   (12.11.04 15:02) [9]


а посмотреть, как это реализовано в коде родного дельфийского Инспектора объектов, в голову не приходило ? исходники-то имеются !
ты же не удивляешься, что Инспектор как-то умудряется показать, что общим для кучи самых разношерстных выделенных компонентов формы явл-ся одно-единственное св-вом , к примеру, Tag, и разом установить его для всех у кого оно имеется ?

все пляшет  вокруг RTTI !



Страницы: 1 вся ветка

Текущий архив: 2004.11.28;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.023 c
3-1098884695
gorvic
2004-10-27 17:44
2004.11.28
Добавление в Query в run-time поля типа fkCalculated


1-1100200566
xkiller
2004-11-11 22:16
2004.11.28
В exe-файле несколько разных иконок


4-1097750561
UserUserov
2004-10-14 14:42
2004.11.28
Послать переменную в другую программу??


14-1100075555
}|{yk
2004-11-10 11:32
2004.11.28
Вышел Thunderbird 0.9


1-1100245000
Семен
2004-11-12 10:36
2004.11.28
F :TextFile и поиск по нему