Последствия присвоения себя - PullRequest
3 голосов
/ 06 апреля 2010

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

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

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

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

Ответы [ 3 ]

6 голосов
/ 06 апреля 2010

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

2 голосов
/ 06 апреля 2010

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

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

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

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

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

1 голос
/ 06 апреля 2010

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

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

...