воскресенье, 18 января 2009 г.

Помощники записей

Сегодня, разбираясь с проектом, который я пытаюсь перевести на Delphi 2009, натолкнулся на одну забавную недокументированную возможность. Наряду с помощниками классов (Class Helpers) введенными в последних версиях Delphi, разработчику доступны и помощники записей!

Стоит сразу отметить, что данная возможность не поддерживается редактором кода и Code Insight. Так в редакторе код подчеркивается красным, а в Code Insight добавленное недоступно.

НО, с точки зрения компилятора, следующий код абсолютно рабочий:

type
TRectHelper = record helper for TRect
function Width: integer;
end;

{ TRectHelper }

function TRectHelper.Width: integer;
begin
Result := Self.Right - Self.Left;
end;

Использовать новый метод можно, например, следующим образом:

var
p: TRect;
begin
p.Top := 0;
p.Left := 0;
p.Bottom := 12;
p.Right := 12;
ShowMessage(inttostr(p.width));
end;

Не знаю, на сколько эта возможность может быть востребована, но она есть.

P.S. К слову сказать, что Class Helpers разработчики не рекомендуют использовать постоянно, а про Record Helpers они и вообще умолчали. :)

3 комментария:

  1. А чем они объясняют свою рекомендацию не использовать часто Class Helpers ?

    ОтветитьУдалить
  2. Они, не рекомендуют, поскольку эта возможность потенциально может быть источником трудноуловимых багов. И я так думаю, то что я описал в следующем посте про то как компилятор видит только один хелпер - далеко не единственный подводный камень.

    ОтветитьУдалить
  3. А вот так сработает

    program Project37;
    uses
    SysUtils,
    Unit36 in 'Unit36.pas';

    {$APPTYPE CONSOLE}


    type
    TSomeObjectHelper2 = class helper for TSomeObject
    function z: integer;
    end;


    { TSomeObjectHelper2 }

    function TSomeObjectHelper2.z: integer;
    begin
    result := 2;
    end;

    var
    obj:TSomeObject;
    begin
    obj := TSomeObject.Create;
    try
    writeln(obj.z);
    writeln( UseY(obj));
    readln;
    except
    on E:Exception do
    Writeln(E.Classname, ': ', E.Message);
    end;
    end.


    unit Unit36;
    interface

    type
    TSomeObject = class
    function X: integer;
    end;

    TSomeObjectHelper = class helper for TSomeObject
    function y: integer;
    end;

    { TSomeObjectHelper }

    function UseY(const obj: TSomeObject):Integer;



    implementation


    function UseY(const obj: TSomeObject):Integer;
    begin
    Result := obj.y;
    end;

    function TSomeObjectHelper.y: integer;
    begin
    result := 1;
    end;

    { TSomeObject }

    function TSomeObject.X: integer;
    begin
    result := 0;
    end;


    Да и в справке написано буквально следующее

    You can define and associate multiple class helpers with a single class type. However, only zero or one class helper applies in any specific location in source code. The class helper defined in the nearest scope will apply. Class helper scope is determined in the normal Delphi fashion (i.e. right to left in the unit's uses clause).

    ОтветитьУдалить