문제

델파이 (아마도 다른 많은 언어들)에는 수업 도우미가 있습니다. 이들은 기존 클래스에 추가 방법을 추가하는 방법을 제공합니다. 서브 클래스를 만들지 않고.

그렇다면 수업 도우미에게는 좋은 용도가 무엇입니까?

도움이 되었습니까?

해결책

나는 그들을 사용하고있다 :

  • 에게 열거자를 삽입하십시오 구현하지 않는 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 }
    
  • 레코드 필드에 대한 액세스를 단순화합니다 캐스팅을 제거하십시오.

다른 팁

처음에 나는 수업 도우미에 대해 회의론자였습니다. 그러나 나는 흥미로운 것을 읽었다 블로그 항목 그리고 지금 나는 그들이 실제로 유용하다고 확신합니다.

예를 들어, 기존 인스턴스 클래스에 대한 추가 기능을 원하고 어떤 이유로 든 기존 소스를 변경할 수 없습니다. 이 기능을 추가하기 위해 클래스 헬퍼를 만들 수 있습니다.

예시:

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

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

매번, 우리는 이제 (서브 클래스) tstrings 인스턴스를 사용하고 tstringshelper는 범위 내에 있습니다. 우리는이 방법에 액세스 할 수 있습니다.

예시:

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

메모:

  • 클래스 도우미는 별도의 장치에 저장 될 수 있으므로 자신의 멋진 클래스 도우미를 추가 할 수 있습니다. 이 장치들에게 클래스 부서의 도우미를위한 클래스 쉘퍼와 같은 기억하기 쉬운 이름을 제공하십시오.
  • 레코드 도우미도 있습니다.
  • 스코프 내에 여러 클래스 도우미가있는 경우 일부 문제를 예상하면 하나의 도우미 만 사용할 수 있습니다.

이것은 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;

그런 다음 변환기를 정의하십시오. 하나의 경고 : 수업 돕는 사람 수업이 아닙니다 친구. 이 기술은 공개 방법과 속성을 통해 새로운 tmyclass 객체를 완전히 설정할 수있는 경우에만 작동합니다. 그러나 가능하다면 정말 잘 작동합니다.

"클래스 헬퍼"라고 부르는 것을 처음 경험 한 것은 목표를 배우는 동안 C. Cocoa (Apple의 목표 C 프레임 워크)가 "카테고리"라고하는 것을 사용하는 것입니다.

카테고리를 사용하면 서브 클래싱없이 자신의 메소드를 추가하여 기존 클래스를 확장 할 수 있습니다. 실제로 Cocoa는 가능한 경우 서브 클래싱을 피하도록 권장합니다. 종종 서브 클래스에 의미가 있지만 종종 카테고리를 사용하여 피할 수 있습니다.

코코아에서 카테고리를 사용하는 좋은 예는 "키 값 코드 (KVC) 및"키 값 관찰 (KVO) "입니다.

이 시스템은 두 가지 범주 (nskeyValuecoding 및 nskeyValueObserving)를 사용하여 구현됩니다. 이 카테고리는 원하는 클래스에 추가 할 수있는 메소드를 정의하고 구현합니다. 예를 들어 Cocoa는 이러한 범주를 사용하여 다음과 같은 NSARRAY에 메소드를 추가하여 KVC/KVO에 "준수"를 추가합니다.

- (id)valueForKey:(NSString *)key

NSARRAY 클래스에는이 방법의 선언이나 구현이 없습니다. 그러나 카테고리 사용을 통해. NSARRAY 클래스에서 해당 메소드를 호출 할 수 있습니다. KVC/KVO 적합성을 얻기 위해 NSARRAY를 서브 클래스 할 필요는 없습니다.

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;

이 의견을 읽었으므로 사용하지 않는 것이 좋습니다.

"자신의 응용 프로그램에서 POV를 사용하는 클래스 헬퍼의 가장 큰 문제는 주어진 클래스의 클래스 도우미가 언제라도 범위에있을 수 있다는 사실입니다." ... "즉, 두 명의 도우미가 범위에있는 경우 컴파일러가 한 명만 인식 할 것입니다. 숨겨져있는 다른 도우미에 대한 경고 나 힌트를 얻지 못할 것입니다."

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

나는 클래스 전체에 걸쳐 사용 가능한 클래스 방법을 일관되게 만드는 데 사용되는 것을 보았습니다. 활성 및 가시적 특성이 아닌 주어진 "유형"의 모든 클래스에 열린/닫기 및 표시/숨기기.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top