Мой класс и "Argument cannot be assigned to"

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Мой класс и "Argument cannot be assigned to"

Сообщение kotompazb » 18.11.2017 23:40:01

В общем, понимаю, что это основы, но все-таки.
Создаю класс так:
Код: Выделить всё
  TSomeItem = record
    SomeField1: Byte;
    SomeField2: Word;
    SomeField3: DWord;
  end;

  { TSomeClass }

  TSomeClass = class(TObject)
  Protected
    FItems: array of TSomeItem;
    function GetItem(Index: Integer): TSomeItem;
    procedure SetItem(Index: Integer; AItem: TSomeItem);
  Public
    Constructor Create;
    Property Items[Index: Integer]: TSomeItem Read GetItem Write SetItem; default;
    Destructor Destroy; override;
  end;

//...

function TSomeClass .GetItem(Index: Integer): TSomeItem;
begin
  Result:=FItems[Index];
end; 

procedure TSomeClass .SetItem(Index: Integer; AItem: TSomeItem);
begin
  FItems[Index]:=AItem;
end;   

Вроде бы все правильно.
Однако когда пытаюсь присвоить значение какому-либо полю свойства Items:
Код: Выделить всё
  var SomeVar: TSomeClass;

//...

  SomeVar:=TSomeClass.Create;
  SomeVar.Items[0].SomeField1:=1;
  SomeVar[0].SomeField1:=1;
,
получаю
Error: Argument cannot be assigned to

Ну и собственно вопрос: ЧЯДНТ?
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Мой класс и "Argument cannot be assigned to"

Сообщение LearnMagic » 19.11.2017 01:48:53

kotompazb писал(а):Ну и собственно вопрос: ЧЯДНТ?

Неправильная работа с Items: procedure SetItem(Index: Integer; AItem: TSomeItem);

Код: Выделить всё
var
  wItem: TSomeItem;
....
  wItem.SomeField1:=1; wItem.SomeField2:=2; wItem.SomeField3:=3;
  SomeVar[0] := wItem;
...

Написано же английким по белому: "Аргумент не может быть назначен"
LearnMagic
новенький
 
Сообщения: 66
Зарегистрирован: 10.11.2016 23:13:38

Re: Мой класс и "Argument cannot be assigned to"

Сообщение kotompazb » 19.11.2017 01:59:02

О! А так просто что ли, без лишней переменной, нельзя? Я почему-то думал, что можно. Просто, если Items - это массив, например, байт, а не записей, то можно. Значит думал неправильно. Спасибо.
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Мой класс и "Argument cannot be assigned to"

Сообщение runewalsh » 19.11.2017 02:00:44

Думай о чтении свойства как о чтении переменной во временную копию (причём константную), т. е. твой код эквивалентен
Код: Выделить всё
var
   SomeVar: TSomeClass;
   Item: TSomeItem;
// ...
   SomeVar := TSomeClass.Create;
   Item := SomeVar[0];
   Item.SomeField1 := 1;

Как ты понимаешь, это не изменит значения внутри SomeVar, а из-за константности — и не компилируется вообще. Будет работать, если TSomeItem будет классом — тогда константным будет указатель, но не содержимое объекта. Либо, менее удобно:
Код: Выделить всё
property Items[Index: Integer]: PSomeItem Read GetItem Write SetItem; default;

function TSomeClass .GetItem(Index: Integer): PSomeItem;
begin
   Result := @FItems[Index];
end;

SomeVar.Items[0]^.SomeField1 := 1;

— но тогда придётся дописывать крышечки (как в последней строке — с классами это происходит «под капотом») и желательно отказаться от сеттера (в конструкции вида Items[0]^ := XYZ всё равно отработает геттер Items, не сеттер).
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: Мой класс и "Argument cannot be assigned to"

Сообщение kotompazb » 19.11.2017 02:59:54

Спасибо.
Ну я пока через временную переменную сделаю. Все равно в будущем присваивание спрячется внутрь самого класса. Снаружи останется только чтение.
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4

Рейтинг@Mail.ru