Pergunta

Delphi (e provavelmente um monte de outras línguas) tem auxiliares de classe. Estes fornecem uma maneira de adicionar métodos extra para uma classe existente. Sem fazer uma subclasse.

Então, o que são bons usos para auxiliares de classe?

Foi útil?

Solução

Eu estou usando-os:

  • para inserção recenseadores em classes VCL que não implementá-las.
  • melhorar aulas VCL.
  • Para adicionar métodos para a classe TStrings para que eu possa usar os mesmos métodos em minhas listas derivados e na 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 }
    
  • Para simplificar o acesso aos campos de registro e fundição remover .

Outras dicas

No começo eu estava meio cético sobre auxiliares de classe. Mas então eu li um entrada de blog interessante e agora estou convencido de que eles são realmente úteis.

Por exemplo, se você quiser funcionalidade extra para uma classe instância existente e por algum motivo você não é capaz de mudar a fonte existente. Você pode criar um auxiliar de classe para adicionar essa funcionalidade.

Exemplo:

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

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

Cada vez, nós agora usar uma instância de (uma subclasse de) TStrings e TStringsHelper está dentro do escopo. Nós temos acesso ao método IsEmpty.

Exemplo:

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

Notas:

  • auxiliares de classe pode ser armazenado em uma unidade separada, para que você pode adicionar seus próprios auxiliares de classe bacana. Certifique-se de dar a essas unidades um nome fácil de lembrar como ClassesHelpers para ajudantes para a unidade de Classes.
  • Há também ajudantes recordes.
  • Se houver vários auxiliares de classe dentro do escopo, esperar alguns problemas, apenas um ajudante pode ser usado.

Isto soa muito bem como métodos de extensão em C # 3 (e VB9). O melhor uso que eu vi para eles é as extensões para IEnumerable<T> (e IQueryable<T>) que permite o trabalho LINQ contra seqüências arbitrárias:

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

(ou o que, é claro). Tudo isso é factível, porque os métodos de extensão permitem que você efetivamente convoca cadeia para métodos estáticos que têm o mesmo tipo como eles retornam.

Eles são muito úteis para plug-ins. Por exemplo, digamos que o seu projeto define uma determinada estrutura de dados e é salvo em disco de uma certa maneira. Mas, então, algum outro programa faz algo muito semelhante, mas o arquivo de dados é diferente. Mas você não quer inchar o seu EXE com um monte de código de importação para uma característica que muitos de seus usuários não vão precisar usar. Você pode usar um quadro plugin e colocar importadores em um plugin que funcionaria assim:

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

E, em seguida, definir o conversor. Uma ressalva: a classe helper não é uma classe amigo . Esta técnica só funcionará se é possível completamente configurar um novo objeto TMyClass através de seus métodos públicos e propriedades. Mas se você puder, ele funciona muito bem.

A primeira vez que me lembro de experimentar o que você está chamando "ajudantes de classe" era ao mesmo tempo aprender os usos que são chamados Objective C. Cacau (quadro C Objetivo da Apple) "Categorias".

A categoria permite que você estender uma classe existente adicionando-lhe próprios métodos sem subclassificação. Na verdade Cacau incentiva você a evitar subclasse quando possível. Muitas vezes faz sentido subclasse, mas muitas vezes pode ser evitado usando categorias.

Um bom exemplo do uso de uma categoria em Cocoa é o que é chamado de "Key Código Valor (KVC)" e "Key Valor Observing (KVO)."

Este sistema é implementado usando duas categorias (NSKeyValueCoding e NSKeyValueObserving). Estas categorias definir e implementar métodos que podem ser adicionados a qualquer classe que você deseja. Por exemplo Cacau acrescenta "conformidade" para KVC / KVO usando essas categorias para adicionar métodos para NSArray, tais como:

- (id)valueForKey:(NSString *)key
classe

NSArray não tem tanto uma declaração nem uma implementação deste método. No entanto, através da utilização da categoria. Você pode chamar esse método em qualquer classe NSArray. Você não é obrigado a subclasse NSArray para ganhar KVC / KVO conformidade.

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

Usando esta técnica torna mais fácil para adicionar suporte KVC / KVO para suas próprias classes. interfaces Java permitem que você adicione declarações de método, mas categorias permitem que você também adicionar as implementações reais para classes existentes.

mostra como GameCat, TStrings é um bom candidato para evitar a digitação:

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;

Alguma vez você precisa acesso multi cordas linha no registro?

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;

Eu não recomendo usá-los, desde que eu ler este comentário:

"O maior problema com a classe ajudantes, do p.o.v de usá-los em seus próprios aplicativos, é o fato de que apenas um ajudante de classe para um determinado classe pode estar no escopo a qualquer momento ". ... "Ou seja, se você tem dois ajudantes no espaço, apenas um será reconhecido pelo compilador. Você não terá qualquer avisos ou até mesmo dicas sobre qualquer outro ajudantes que podem ser escondido ".

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

Eu os vi usado para fazer métodos de classe disponíveis consistentes em classes: Adição de abrir / fechar e Show / Hide para todas as classes de um determinado "tipo" ao invés de propriedades só activa e visível.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top