사용 — 헬퍼 메서드의 범위와 uses 절

사용 — 헬퍼 메서드의 범위와 uses 절

헬퍼 클래스가 정의되면, 그 헬퍼 클래스가 범위 안에 있을 때마다 그 메서드를 사용할 수 있어요. 즉 별도의 유닛에 정의했다면, 헬퍼 클래스의 메서드를 사용하는 곳마다 그 유닛이 uses 절에 있어야 해요.

출처: Usage — Free Pascal Reference

본문

다음 유닛을 보세요.

{$mode objfpc}
{$h+}
unit oha;

interface

Type
  TObjectHelper = class helper for TObject
    function AsString(const aFormat: String): String;
  end;

implementation

uses sysutils;

function TObjectHelper.AsString(const aFormat: String): String;

begin
  Result := Format(aFormat, [ToString]);
end;

end.

그러면 다음은 컴파일돼요.

Program Example113;

uses oha;

{ Program to demonstrate the class helper scope. }

Var
  o : TObject;

begin
  O:=TObject.Create;
  Writeln(O.AsString('O as a string : %s'));
end.

하지만 두 번째 유닛(ohb)을 만들면:

{$mode objfpc}
{$h+}
unit ohb;

interface

Type
  TAObjectHelper = class helper for TObject
    function MemoryLocation: String;
  end;

implementation

uses sysutils;

function TAObjectHelper.MemoryLocation: String;

begin
  Result := format('%p',[pointer(Self)]);
end;

end.

그리고 이 유닛을 uses 절의 첫 번째 유닛 뒤에 추가하면:

Program Example113;

uses oha,ohb;

{ Program to demonstrate the class helper scope. }

Var
  o : TObject;

begin
  O:=TObject.Create;
  Writeln(O.AsString('O as a string : %s'));
  Writeln(O.MemoryLocation);
end.

컴파일러는 "AsString" 메서드를 모른다고 불평할 거예요. 컴파일러는 첫 번째 클래스 헬퍼를 만나는 즉시 클래스 헬퍼를 찾는 것을 멈추기 때문이에요. ohb 유닛이 uses 절에서 마지막에 오므로 컴파일러는 TAObjectHelper만 클래스 헬퍼로 사용해요.

해결책은 유닛 ohb를 재구현하는 거예요.

{$mode objfpc}
{$h+}
unit ohc;

interface

uses oha;

Type
  TAObjectHelper = class helper(TObjectHelper) for TObject
    function MemoryLocation: String;
  end;

implementation

uses sysutils;

function TAObjectHelper.MemoryLocation: String;

begin
  Result := format('%p',[pointer(Self)]);
end;

end.

그리고 유닛 ohbohc로 교체하면 예제 프로그램은 예상대로 컴파일되고 동작해요.

클래스 헬퍼가 있는 유닛을 프로젝트에 한 번 포함하는 것만으로는 충분하지 않다는 점을 주의하세요. 클래스 헬퍼가 필요할 때마다 그 유닛을 포함해야 해요.

핵심은 컴파일러가 uses 절에서 마지막 클래스 헬퍼 하나만 사용한다는 거예요. 두 헬퍼를 함께 쓰고 싶으면 첫 번째 헬퍼에서 파생시켜 하나로 합쳐야 해요.

더 알아보기