Имеем код
type
TVec2f = packed record
X, Y: Single;
end;
TClass = class
private
FVec: TVec2f;
procedure SetVec(V: TVec2f);
public
property Vec: TVec2f read FVec write SetVec;
end;
procedure TClass.SetVec(V: TVec2f);
begin
FVec := V;
Writeln(V.X, ' ', V.Y);
end;
var
Obj: TClass;
V: TVec2f;
begin
Obj := TClass.Create;
V.X := 100;
V.Y := 1000;
Obj.Vec := V;
Obj.Vec.Y := 666;
Writeln('Last value: ', Obj.Vec.Y);
end.
Код прекрасно компилируется. Вся соль в предпоследней строке Obj.Vec.Y := 666. Возникает несколько вопросов
1) Будет ли вызван Writeln при выполнении этой строки?
2) Что будет напечатано в самом конце?
Ответы
1) Нет
2) "Last value: 6.660000000E+02"
Из-за этого совершенно неочевидного поведения я просидел в поисках ошибки в одной своей программе около часа.
Далее, если в этом же коде убрать "read FVec" и "Writeln('Last value: ', Obj.Vec.Y);", то компилятор будет ругаться на строку "Obj.Vec.Y := 666;".
От нас что-то скрывают! :)
Видимо, теперь record ведет себя как класс. В предыдущих версиях фпц такой код вообще не компилировался.
2 комментария:
Да, сталкивался с похожим. Но компилятор можно понять, ведь ты изменяешь только одно поле у TVec2f, как ему при этом вызывать SetVec(V: TVec2f), не заполнять же структуру для вызова. Неплохо бы хинт или варнинг выдавать в таких местах.
>Далее, если в этом же коде убрать "read FVec" и >"Writeln('Last value: ', Obj.Vec.Y);", то компилятор >будет ругаться на строку "Obj.Vec.Y := 666;".
Если правильно понял, получится write only свойство
В Free Pascal'е сталкивался? Да, компилятор прав, просто несколько неожиданно, раньше он на такое ругался :) На счет хинта и варинга ты прав, было бы неплохо.
> Если правильно понял, получается wirte only свойство
Да, именно так, я этим проверял то, что для Obj.Vec.Y := 666 необходима именно read возможность.
Вообще, это немножнко подрывает философию паскалевских record'ов и property :)
Отправить комментарий