Вопрос

В Delphi (и, вероятно, во многих других языках) есть помощники классов.Они предоставляют способ добавить дополнительные методы к существующему классу.Без создания подкласса.

Итак, чем хороши помощники по классу?

Это было полезно?

Решение

Я ими пользуюсь:

  • Для вставить счетчики в классы VCL, которые их не реализуют.
  • Для улучшить Классы VCL.
  • Добавить методы в класс TStrings, чтобы я мог использовать те же методы в мои производные списки и в TStringList.

    TGpStringListHelper = class helper for TStringList
    public
      function  Last: string;
      function  Contains(const s: string): boolean;
      function  FetchObject(const s: string): TObject;
      procedure Sort;
      procedure Remove(const s: string);
    end; { TGpStringListHelper }
    
  • Для упрощения доступа к полям записи и удалить отливку.

Другие советы

Сначала я довольно скептически относился к классным помощникам.Но потом я прочитал интересную запись в блоге и теперь я убежден, что они действительно полезны.

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

Пример:

type
  TStringsHelper = class helper for TStrings
  public
    function IsEmpty: Boolean;
  end;

function TStringsHelper.IsEmpty: Boolean;
begin
  Result := Count = 0;
end;

Теперь мы каждый раз используем экземпляр (подкласс) TStrings, и TStringsHelper находится в пределах области видимости.У нас есть доступ к методу isEmpty.

Пример:

procedure TForm1.Button1Click(Sender: TObject);
begin
  if Memo1.Lines.IsEmpty then
    Button1.Caption := 'Empty'
  else
    Button1.Caption := 'Filled';
end;

Примечания:

  • Помощники классов могут храниться в отдельном блоке, так что вы можете добавить свои собственные изящные помощники классов.Обязательно дайте этим устройствам легко запоминающиеся названия, например ClassesHelpers для помощников для подразделения Classes.
  • Есть также помощники по записи.
  • Если в пределах области видимости имеется несколько помощников класса, ожидайте некоторых проблем, можно использовать только одного помощника.

Это очень похоже на методы расширения в C # 3 (и VB9). Лучшее использование, которое я видел для них, это расширения для IEnumerable<T>IQueryable<T>), которые позволяют LINQ работать с произвольными последовательностями:

var query = someOriginalSequence.Where(person => person.Age > 18)
                                .OrderBy(person => person.Name)
                                .Select(person => person.Job);

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

Они очень полезны для плагинов. Например, предположим, что ваш проект определяет определенную структуру данных и определенным образом сохраняется на диск. Но затем какая-то другая программа делает что-то очень похожее, но файл данных другой. Но вы не хотите раздувать ваш EXE с кучей кода импорта для функции, которая не понадобится многим вашим пользователям. Вы можете использовать инфраструктуру плагинов и поместить импортеров в плагин, который будет работать следующим образом:

type
   TCompetitionToMyClass = class helper for TMyClass
   public
      constructor Convert(base: TCompetition);
   end;

А затем определите конвертер. Одно замечание: класс помощник не является классом friend . Этот метод будет работать, только если возможно полностью настроить новый объект TMyClass с помощью его открытых методов и свойств. Но если вы можете, это работает очень хорошо.

В первый раз, когда я помню, я испытывал то, что вы называете " помощники класса " во время изучения Objective C. Какао (Apple's Objective C Framework) использует то, что называется " Categories. "

Категория позволяет расширять существующий класс, добавляя свои собственные методы без создания подклассов. На самом деле какао призывает вас избегать подклассов, когда это возможно. Часто имеет смысл создавать подклассы, но часто этого можно избежать, используя категории.

Хорошим примером использования категории в Какао является то, что называется " Key Value Code (KVC) " и " Наблюдение значения ключа (KVO). "

Эта система реализована с использованием двух категорий (NSKeyValueCoding и NSKeyValueObserving). Эти категории определяют и реализуют методы, которые могут быть добавлены в любой класс, который вы хотите. Например, Какао добавляет & Quot; соответствие & Quot; в KVC / KVO, используя эти категории для добавления методов к NSArray, таких как:

- (id)valueForKey:(NSString *)key

Класс NSArray не имеет ни объявления, ни реализации этого метода. Тем не менее, за счет использования категории. Вы можете вызвать этот метод в любом классе NSArray. Вы не обязаны создавать подкласс NSArray для соответствия KVC / KVO.

NSArray *myArray = [NSArray array]; // Make a new empty array
id myValue = [myArray valueForKey:@"name"]; // Call a method defined in the category

Использование этой техники позволяет легко добавить поддержку KVC / KVO в ваши собственные классы. Интерфейсы Java позволяют добавлять объявления методов, но категории также позволяют добавлять фактические реализации к существующим классам.

Как показывает GameCat, TStrings - это хороший кандидат, чтобы не набирать текст:

type
  TMyObject = class
  public
    procedure DoSomething;
  end;

  TMyObjectStringsHelper = class helper for TStrings
  private
    function GetMyObject(const Name: string): TMyObject;
    procedure SetMyObject(const Name: string; const Value: TMyObject);
  public
    property MyObject[const Name: string]: TMyObject read GetMyObject write SetMyObject; default;
  end;

function TMyObjectStringsHelper.GetMyObject(const Name: string): TMyObject;
var
  idx: Integer;
begin
  idx := IndexOf(Name);
  if idx < 0 then
    result := nil
  else
    result := Objects[idx] as TMyObject;
end;

procedure TMyObjectStringsHelper.SetMyObject(const Name: string; const Value:
    TMyObject);
var
  idx: Integer;
begin
  idx := IndexOf(Name);
  if idx < 0 then
    AddObject(Name, Value)
  else
    Objects[idx] := Value;
end;

var
  lst: TStrings;
begin
  ...
  lst['MyName'] := TMyObject.Create; 
  ...
  lst['MyName'].DoSomething;
  ...
end;
<Ч>

Вам когда-нибудь нужно было получать доступ к многострочным строкам в реестре?

type
  TRegistryHelper = class helper for TRegistry
  public
    function ReadStrings(const ValueName: string): TStringDynArray;
  end;

function TRegistryHelper.ReadStrings(const ValueName: string): TStringDynArray;
var
  DataType: DWord;
  DataSize: DWord;
  Buf: PChar;
  P: PChar;
  Len: Integer;
  I: Integer;
begin
  result := nil;
  if RegQueryValueEx(CurrentKey, PChar(ValueName), nil, @DataType, nil, @DataSize) = ERROR_SUCCESS then begin
    if DataType = REG_MULTI_SZ then begin
      GetMem(Buf, DataSize + 2);
      try
        if RegQueryValueEx(CurrentKey, PChar(ValueName), nil, @DataType, PByte(Buf), @DataSize) = ERROR_SUCCESS then begin
          for I := 0 to 1 do begin
            if Buf[DataSize - 2] <> #0 then begin
              Buf[DataSize] := #0;
              Inc(DataSize);
            end;
          end;

          Len := 0;
          for I := 0 to DataSize - 1 do
            if Buf[I] = #0 then
              Inc(Len);
          Dec(Len);
          if Len > 0 then begin
            SetLength(result, Len);
            P := Buf;
            for I := 0 to Len - 1 do begin
              result[I] := StrPas(P);
              Inc(P, Length(P) + 1);
            end;
          end;
        end;
      finally
        FreeMem(Buf, DataSize);
      end;
    end;
  end;
end;

Я бы не рекомендовал их использовать, так как я прочитал этот комментарий:

  

& "Самая большая проблема с классом"   помощники, из п.о. использования их   в ваших собственных приложениях, это факт   что только один класс помощник для данного   класс может находиться в области видимости в любое время. "   ... & То есть если у вас есть два помощника   по объему распознается только ОДИН   компилятором. Вы не получите   предупреждения или даже намеки на любые другие   помощники, которые могут быть скрыты. "

http://davidglassborow.blogspot.com /2006/05/class-helpers-good-or-bad.html

Я видел, как они использовались для обеспечения доступности методов классов в разных классах: добавление Open / Close и Show / Hide ко всем классам данного " type " а не только активные и видимые свойства.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top