Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.11.28;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.046 c
1-1100242872
Alex P
2004-11-12 10:01
2004.11.28
Создание программы в виде процессса windows


1-1100118517
Jiuradfer
2004-11-10 23:28
2004.11.28
А как програмно возвести число в степень?


14-1100141366
Думкин
2004-11-11 05:49
2004.11.28
С днем рождения! 11 ноября


14-1100034968
Cerberus
2004-11-10 00:16
2004.11.28
Предлогаю альтернотиву


14-1100104995
Александр1
2004-11-10 19:43
2004.11.28
Сломал хард на 200 ГБ





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский