PascalABC.NET

Методы расширения

Любой существующий тип, хранящийся во внешней dll, и все типы стандартной библитеки .NET можно расширить новыми методами. Метод расширения определяется как процедура или функция с модификатором extensionmethod. Первый параметр метода расширения обязательно должен иметь имя Self и принадлежит к расширяемому типу. Сравним две процедуры, описанные ниже:

procedure MyPrint(Self: integer);
begin
  writeln(Self)
end;

procedure
MyPrintEx(Self: integer); extensionmethod;
begin
  writeln(Self)
end;

begin
  MyPrint(1);
  1.MyPrintEx;
end.

Здесь MyPrint - это обычная процедура с параметром типа integer, MyPrintEx - метод расширения типа integer. При этом при вызове первый параметр MyPrintEx становится объектом, вызывающим MyPrintEx как метод.

Можно расширить тип последовательности, тогда все классы, являющиеся последовательностями (динамические одномерные массивы, списки List<T>, множества HashSet<T> и SortedSet<T>), получат этот метод. Например, в системном модуле PABCSystem так введен метод расширения ForEach для последовательностей:

procedure &ForEach<T>(Self: sequence of T; action: T -> ()); extensionmethod;
begin
  foreach x: T in Self do
    action(x);
end;

С помощью методов расширения можно перегружать операции:

function operator+=<T>(a: List<T>; x: T): List<T>; extensionmethod;
begin
  a.Add(x);
  Result := a;
end;

В этом случае первый параметр не обязан иметь имя Self.

Для методов расширения имеется ряд ограничений:

  • Методы расширения не могут быть виртуальными.
  • Если метод расширения имеет то же имя, что и обычный метод, то предпочтение отдаётся обычному методу.