Записать record в TObject

Ognev

ex-Team DUMPz
Joined
Aug 20, 2018
Messages
2,103
Reaction score
902
Age
25
Всем доброго времени суток!

Извиняюсь, если тупой вопрос, но чего-то не осилил. Подскажите, как можно в TObject записать record и с ней потом работать. Пока не получилось даже что-то записать. В старом коде вместо record был class TCoverReliefPiar, и все работало (UserObject : TObject ):
NewGrid.UserObject := TCoverReliefPiar.Create;
Можно ли вместо класса засунуть туда запись?

UPD
Delphi XE10 Seatle.
 
Last edited by a moderator:

rgreat

Member
Joined
Dec 24, 2009
Messages
35
Reaction score
31
Можно, но без програмиста не выйдет.
 

LeshaRB

Staff member
Premium
Joined
Jun 11, 2007
Messages
319
Reaction score
451
Location
Минск
Там надо делать обертку классом, что лучше имхо

type
PMyRec = ^TMyRec;
TMyRec = record
I : integer;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
P : PMyRec;
begin
New(P);
P.I := 42;
ListBox1.AddItem('One',TObject(P));
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
I : integer;
begin
//Free memory
for I := 0 to ListBox1.Items.Count - 1 do
Dispose(PMyRec(ListBox1.Items.Objects));
end;

procedure TForm1.ListBox1Click(Sender: TObject);
var
P : PMyRec;
begin
P := PMyRec(ListBox1.Items.Objects[ ListBox1.ItemIndex ]);
ShowMessage( IntToStr(P.I) );
end;
 

JCDenton

Member
Joined
Feb 15, 2013
Messages
157
Reaction score
40
Проблемы не увидел:

type
TCoverReliefPiar = record
Param: Integer;
end;

TNewGrid = class(...)
private
FUserObject: TCoverReliefPiar;
public
property UserObject: TCoverReliefPiar read FUserObject write FUserObject;
end;

...

var
NewGrid: TNewGrid;
CoverReliefPiar: TCoverReliefPiar;

...

CoverReliefPiar.Param := 1;
NewGrid.UserObject := CoverReliefPiar;

Если вопрос в этом:
NewGrid.UserObject.Param := 1;
то так - нельзя. Записи передаются по значению (в отличие от объектов классов) - следовательно, можно поменять только всё значение целиком (всю запись).

Но можно так:
type
TCoverReliefPiar = record
Param: Integer;
end;
PCoverReliefPiar = ^TCoverReliefPiar;

TNewGrid = class(...)
private
FUserObject: TCoverReliefPiar;
function GetUserObject: PCoverReliefPiar;
procedure SetUserObject(const AValue: PCoverReliefPiar);
public
property UserObject: PCoverReliefPiar read GetUserObject write SetUserObject;
end;

function TNewGrid.GetUserObject: PCoverReliefPiar;
begin
Result := @FUserObject;
end;

procedure TNewGrid.SetUserObject(const AValue: PCoverReliefPiar);
begin
Assert(Assigned(AValue));
FUserObject := AValue^;
end;

...

var
NewGrid: TNewGrid;

...

NewGrid.UserObject.Param := 1;

В этом случае свойство передаётся по указателю.

Если вопрос в этом:
type
TEmptyRecord = record
end;

TCoverReliefPiar = record
Param: Integer;
end;

TNewGrid = class(...)
private
FUserObject: TEmptyRecord;
public
property UserObject: TEmptyRecord read FUserObject write FUserObject;
end;

...

var
NewGrid: TNewGrid;
CoverReliefPiar: TCoverReliefPiar;

...

CoverReliefPiar.Param := 1;
NewGrid.UserObject := CoverReliefPiar;
то - нет, так нельзя. Передача по значению означает статический размер. Наследования в записях нет.

Можно, опять же, переделать всё на указатели, ввести первое поле, определяющее тип/размер записи (на манер dwSize в WinAPI). Но смысл это делать, если есть гораздо более удобные объекты/классы?
 
Last edited by a moderator:

Ognev

ex-Team DUMPz
Joined
Aug 20, 2018
Messages
2,103
Reaction score
902
Age
25
Общее короткое резюме по этому вопросу именно что нужно делать обертку классом. И хранить запись в свойстве или поле - в зависимости от того, что требуется делать с записью и как. Иначе получается извращение.

Всем спасибо за ответы!
 

utmost

Member
Joined
Nov 21, 2020
Messages
15
Reaction score
5
Age
44
Сериализовать запись в JSON объект, с каких-то последних версий дельфи он вроде из коробки есть, и передавать как строку его удобнее, хоть по сети кидай, хоть между приложениями или окнами.
 
Top