Delphi Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
델파이 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
FreePascal/Lazarus
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
델마당
볼랜드포럼 광고 모집

델파이 강좌/문서
Delphi Programming Tutorial&Documents
[104] 기존 콤포넌트를 다른 콤포넌트로 대체하는 방법 Part 3
주정섭 [jjsverylong] 5142 읽음    2006-07-14 16:18
Imposter클래스란 무엇인가?

imposter는 사칭하는 사람이란 뜻이다. 즉 위조 신분증을 가지고 남을 사칭하는 사람을 말한다. 결국, imposter 클래스란, 다른 클래스를 사칭하는 클래스라는 의미가 된다.

임포스터 클래스는 예전에 내가 세미나를 하면서 잠시 소개한 적이 있고, 양병규씨는 이를 변칙적 상속이란 제목으로 소개한 적이 있다. 그런데 임포스터 클래스는 이미 오래전부터 델파이 개발자들 사이에 널리 알려진 방법이다. 심지어 델파이 VCL 소스에서도, 윈도우와 리눅스판 델파이의 소스 호환성을 해결하기 위해 이 기법을 사용한 것으로 알려져 있다.

임포스터 클래스는 기존 클래스명을 바꾸지 않고서도 어떤 기능을 추가하고 싶을 때 가장 많이 사용한다. TEdit 콤포넌트에 어떤 기능을 추가한 새로운 TXEdit라는 콤포넌트를 만들었다고 치자. 이제 모든 TEdit를 TXEdit로 대체하려면, 기존 소스에서 TEdit 콤포넌트를 사용한 부분을 모조리 찾아내어서 TXEdit로 바꿔야 하는데, 이는 아주 간단한 프라젝트가 아니면 매우 힘들 뿐만 아니라, Search and Replace 방식은 항상 뭔가를 빠뜨릴 수 있는 여지가 있기 때문에 별로 좋은 방법이 아니다.

이럴 경우 다음과 같이 임포스터 클래스를 만드는 것이 대부분의 경우 더 나은 대안이다. 예를 들어 별도의 소스에 다음과 같은 TEdit의 임포스터 클래스를 만든다. 다음 소스는 TEdit에 EditCaption이라는 속성을 추가한 TEdit 임포스터 클래스를 만드는 예제다.

---------------------------------------------
unit unXEdit;

interface

uses Dialogs, StdCtrls;

type
  TEdit = class(StdCtrls.TEdit) // <== 이 라인이 중요. 기존 TEdit를 대체하는 임포스터 클래스 정의 
  private
    FEditCaption: string;
  public
    procedure ShowCaption;

  published
    property EditCaption: string read FEditCaption write FEditCaption;
  end;

implementation

procedure TEdit.ShowCaption;
begin
  ShowMessage( FEditCaption );
end;

end.

이제 이 유닛을 기존 폼 소스에서 상단 uses 제일 마지막에 나열하면, 원래 StdCtrs에 정의된 TEdit가 아닌 unXEdit의 TEdit 임포스터 클래스로 대체되는 것이다. 두 클래스는 이름은 같지만 사실 별개의 클래스이다. 임포스터 클래스는  다른 유닛에서 동일한 이름의 클래스를 정의하는 것을 말하는 것이다.

TEdit = class(StdCtrls.TEdit)

임포스터 클래스 정의부를 보면  원래 클래스에서 상속 받는 부분을 볼 수 있다. 임포스터 클래스는 이전 파트 글에서 설명한, uses의 last-win 특성과 유닛의 NameSpace 역할을 합한 효과라고 이해하면 된다.

다음 소스는 기존 폼에서 TEdit를 임포스트 클래스로 대체하는 방법을 보여 준다.

----------------------------------------------------------------
unit fmMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, unXEdit; //<== 반드시 제일 마지막에 추가해야 한다.

type

  TForm1 = class(TForm)
    Edit1: TEdit;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

end.


실행시 이폼에 있는 모든 TEdit는 원래의 TEdit가 아닌, unXEdit의 TEdit  임포스터 클래스로 대체된다. 여기서 중요한 것은 실행시에만 대체 된다는 것이다. 폼 디자인시에는 여전히 원래의 TEdit를 인식하기 때문에,  EditCaption이 속성창에 나타나지 않는다.

이것이 바로 임포스터 클래스의 단점이다. 폼 디자이너는 임포스터 클래스를 알 수 없다. 임포스터 클래스에서 추가한 속성들은 속성창에서 나타나지 않기 때문에, 오로지 코드로만 값을 세팅할 수 있다.  그러나, 이 단점은 내가 보기에는 별로 큰 단점이 아니다. 실행시 중대한 영향을 미치는 속성값(예를 들어 Enabled, Visible 등)들은 폼디자이너의 속성창을 통해서 세팅하기 보다는, 코드로 세팅하라고 주위 사람들에게 나는 가르킨다. 이렇게 하면 후일 여러모로 편리한 점이 많기 때문이다. 따라서 임포스터 클래스 같이 약간 예외적인 클래스의 객체인 경우, 모든 속성 역시 코드로 세팅함이 바람직한 코딩 방식이다.

이제 모든 폼의 TEdit를 이 새로운 TEdit로 대체하려면 .dfm 파일은 전혀 건드릴 필요없이, 폼 소스 파일의 상단 uses 문에 unXEdit만 추가해주면 된다. 임포스터 클래스는 일반 클래스와 다를 바 없기 때문에, 메서드 오버라이드, 오버로딩, 새로운 이벤트 추가, 속성 추가 등에서 아무런 제약이 없다. 즉 콤포넌트 팔레트에 등록만 되지 않을 뿐, 새로운 콤포넌트를 만드는 것과 거의 동일한 역할을 한다는 것이다.



만일, 모든 폼이 아닌 특정 폼의 TEdit만 대체하려면 다음과 같은 식으로 소스를 작성하면 된다.

unit fmMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type

  TEdit = class(StdCtrls.TEdit) // 반드시 폼 클래스 이전에 정의해야 한다.
    // 중략
  end;
   
  // 실행시 이폼의 모든 TEdit는 이 폼 자체의  TEdit 임포스터 클래스로 자동 대체된다.
  TForm1 = class(TForm)
    Edit1: TEdit;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  // 중략

임포스터 클래스는 이름이 주는 나쁜 느낌보다는 의외로 매우 유용한 놈이다. 디버깅시에 기존 클래스 소스를 변경하지 않고서도, 특정 클래스 기능을 바꾸는 용도로도 활용할 수 있다.

단 조심할 점은, 임포스터 클래스를 사용한 유닛은 반드시 코멘트를 해둬야 한다는 것이다. 그렇지 않으면 기존의 TEdit 가 동작하는 것으로 오인할 수도 있기 때문이다. 좋은 코멘트는 주리장창 장황한 것이 아니라, 요점을 콕 찝어서 적는 것이다. 특히 후일 오해하기 쉽거나, 실수할 수 있는 내용을 기술하는 것이 매우 중요하다.

+ -

관련 글 리스트
104 기존 콤포넌트를 다른 콤포넌트로 대체하는 방법 Part 3 주정섭 5142 2006/07/14
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.