Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

record в property [D6, Win2k]


sokoloff ©   (2002-07-02 16:13:00) 

День добрый, подскажите как правильно преписать код.
Есть:

type
TRow = record
Name: string;
Caption: string;
ID : integer;
Value: string;
end;


TMyTable = class
private
FRows: array[0..16] of TRow;
function GetValues(Index: integer): TRow;
procedure SetValues(Index: integer; const Value: TRow);
public
property Values[Index: integer]: TRow read GetValues write SetValues;
end;


function TMyTable.GetValues(Index: integer): TRow;
begin
result:=Frow[Index];
end;


procedure TMyTable.SetValues(Index: integer; const Value: TRow);
begin
FRow[Index]:=Value;
end;



Т.е. в классе есть свойство-массив Values, каждое значение это запись из нескольких полей.

Не работает такой код:

MyTable.Values[2].ID:=2;

Компилятор выдает:
[Error] UnitFLT.pas(174): Left side cannot be assigned to

Можно, конечно, сделать так:


var
NewRow: TRow;
begin
NewRow.ID:=2;
MyTable.Values[2]:=NewRow;


Но хотелось бы как в первом варианте. Можно как-нибудь переписать код класса чтоб можно было присваивать значения напрямую? Если можно, то как?


Sokoloff   (2002-07-02 18:45:00) [1]

Первый вариант не работает :(
А сделал я все гораздо проще, не public property которое ссылается на private array, а просто public array, т.е.


TMyTable = class
private
public
Values : array[0..16] of TRow;
end;

Плохо то,что нет возможности проверять значения перед записью, правда пока это и не надо, но как-то некрасиво. Но в вариантах с указателями, насколько я вижу это то-же невозможно. Чтоб проверять записи надо делать не record, а class.


Толик   (2002-07-02 17:45:00) [2]

Прошу прощения за опечатку, ф-я GetValues должна выглядеть так:

function TMyTable.GetValues(Index: integer): PRow;
begin
result := @Frow[Index];
end;


Толик   (2002-07-02 17:40:00) [3]

Надо объявить св-во с типом не структуры, а УКАЗАТЕЛЕЯ на структуру.
вот Ваш несколько видоизменённый код:

type
TRow = record
Name: string;
Caption: string;
ID : integer;
Value: string;
end;
PRow = ^TRow;

TMyTable = class
private
FRows: array[0..16] of TRow
function GetValues(Index: integer): PRow;
procedure SetValues(Index: integer; const Value: PRow);
public
property Values[Index: integer]: PRowread GetValues write SetValues;
end;


function TMyTable.GetValues(Index: integer): PRow;
begin
result := Frow[Index];
end;


procedure TMyTable.SetValues(Index: integer; const Value: PRow);
begin
FRow[Index]:=Value ^;
//а вот здесь следует помнить о том, что прежде чем передать в эту ф-ю значение Value, под него надо выделить память, а освобожлать её ТОЛЬКО ПОСЛЕ удаления эл-та из массива!!!
end;

Ну и соответственно обращаться к этому св-ву надо так:

MyTable.Values[2]^.ID:=2;


Dimka Maslov   (2002-07-02 17:15:00) [4]

type
PRow = ^TRow;
TRow = record
Name: string;
Caption: string;
ID : integer;
Value: string;
end;


TMyTable = class
private
FRows: array[0..16] of TRow;
function GetValues(Index: integer): PRow;
public
property Values[Index: integer]: PRow read GetValues; end;


function TMyTable.GetValues(Index: integer): PRow;
begin
result:=@Frow[Index];
end;




Ivan2   (2002-07-02 16:57:00) [5]

Так как ты хочешь не может работать. Когда ты пишешь MyTable.Values[2]:=NewRow, компилятор фактически
генерит след. код: MyTable.SetValues(2, NewRow)т.е. вызывает метод для присвоения значения твоему
свойству. Если хочешь, открой во время выполнения этой строчки окно ассемблерного кода. Естественно, что запись MyTable.Values[2].ID:=2в этом случае некорректна в левой части присваивания (заметь, в правой - без проблем).

Попробуй переписать свой класс так:


type
TRowArray: array[0..16] of TRow;

TMyTable = class
private
FRows: TRowArray;
function GetValues(Index: integer): TRow;
procedure SetValues(Index: integer; const Value: TRow);
public
property Values: TRowArray read FRows;
// property Values[Index: integer]: TRow read GetValues write SetValues;
end;

Тогда ты смошеь обрашяться к массиву свободно и без извращений:
MyTable.Values[2] := NewRow
MyTable.Values[2].ID := 2
MyTable.Values[3].Name := MyTable.Values[10].Name


и т.д.


Наверх

Титульная страница Поиск, карта сайта Написать письмо