Последствия присвоения себя

Сегодня нашел кусок кода, который я нахожу немного вонючим...

TMyObject.LoadFromFile(const filename: String);
begin
  if fileExists(filename) then
    self := TSomeObjectStreamer.ReadObjectFromFile(filename);
end;

Если этот код сработает, по крайней мере произойдет утечка памяти, но работает ли он?
Можно ли присваивать себе таким образом?

Что, если передаваемый в потоковом режиме объект относится к другому подклассу, чем исходное «я»?
Что, если передаваемый в потоковом режиме объект относится к другому классу, не имеющему общего предка с исходным «я»?


person Vegar    schedule 06.04.2010    source источник
comment
возможный дубликат stackoverflow.com/questions/814567 /   -  person gabr    schedule 06.04.2010
comment
Как вы думаете, что в данном контексте означает работа? Что должен делать этот код, чтобы вы считали его работающим?   -  person Rob Kennedy    schedule 06.04.2010
comment
Когда я читаю этот код, я предполагаю, что цель состоит в том, чтобы заменить экземпляр объекта новым экземпляром, полученным из файла. Вызывающая функция LoadFromFile() должна ожидать, что ссылка на экземпляр TMyObject теперь будет указывать на новый экземпляр.   -  person Vegar    schedule 12.04.2010


Ответы (3)


Вы можете назначить Self, но это только локальная переменная, и вы ничего не измените выходит за рамки этого метода. Таким образом, этот код почти наверняка не будет делать то, что исходный кодировщик, по-видимому, думает, что он будет делать.

person Mason Wheeler    schedule 06.04.2010

Учтите, что метод эквивалентен свободной процедуре, принимающей Object в качестве первого параметра с именем Self:

TMyClass.MyRoutine({args})  <=>  MyRoutine(Self: TMyClass {; args})

Имея это в виду, вы видите, что вы можете локально изменить содержимое Self, не повреждая исходный объект.

Но вы правы, это действительно вонючий и очень подвержен ошибкам.

Я бы не принял такой код без очень сильного убедительного аргумента в комментарии...

person Francesca    schedule 06.04.2010
comment
Почему-то от твоего использования жирного шрифта у меня звенит в ушах. - person dummzeuch; 06.04.2010
comment
@dummzeuch, ... так что это шумное предупреждение о вонючем коде! ;-) - person Francesca; 06.04.2010

да, вы можете использовать self как локальную временную переменную, даже если здесь это бесполезно. Но в этом случае передаваемый объект должен быть того же класса, что и сам (TMyObject), иначе компилятор обнаружит ошибку, поскольку типы несовместимы.

В вашем примере TSomeObjectStreamer.ReadObjectFromFile() должен вернуть TMyObject или ваш компилятор должен предупредить вас (или выдать ошибку)

person TridenT    schedule 06.04.2010