본문 바로가기
Delphi/문법

델파이 메소드 포인터(Method Pointer)

by MonoSoft 2023. 10. 24.
728x90
반응형

델파이 메소드 포인터(Method Pointer)

728x90

 

 

프로시저 형 (Procedural Type)

: C 언어의 함수 포인터와 유사한 개념.

정수나 문자열 변수 뿐 아니라 프로시저를 변수로 사용할 수 있다.

 

type

  TestProc = procedure (var Param: Integer);

 

다음과 같이 선언된 프로시저 형의 변수 TestProc이 있다.

이것은 레퍼런스에 의해 전달되는 정수 파라미터의 프로시저 형의 변수를 뜻한다.

 

이 프로시저 형은 정확하게 같은 파라미터를 갖는 루틴이면

어느 것과도 호환이 된다.

 

procedure DoubleProc (var Value: Integer);

begin

  Value := Value * 2;

end;

 

procedure TripleProc (var Value: Integer);

begin

  Value := Value * 3;

end;

 

위에서 두 개의 프로시저를 정의했다.

그러면 프로시저 형을 어떻게 사용할 수 있는가에 대해 알아보자.

 

아래의 두 변수를 유닛안에서 모두 사용할 수 있도록 선언을 하자.

그러기 위해서는 폼 클래스 내부 혹은 전역변수로 선언하여야 한다.

 

TP: TestProc;

X: Integer;

 

원하는 이벤트에 다음을 추가하자.

 

begin

  X := 5;

  TP := DoubleProc; TP(X);

  TP := TripleProc; TP(X);

end;

 

이것은

 

var

  X: Integer;

begin

  X := 5;

  DoubleProc(X);

  TripleProc(X);

end;

 

과 동일하다.

 

여기서는 오히려 프로시저 형을 사용한 경우가 더 복잡하지만

일단 사용 예를 보여주는 것 뿐이므로 그냥 이해하도록 하자.

 

이 프로시저 형은 아주 진보된 언어 기술로서

이와 관련해 다음에 다룰 내용들의 기본이 된다.

 

 

메소드 포인터 (Method Pointer) 

: 프로시저 형과 비슷하지만 메소드를 가리키는 경우이다.

기술적으로, 메소드 포인터 형은 self 파라미터를 갖는 프로시저 형이다.

 

이것은 델파이 컴포넌트 기술의 기초 중의 하나이다.

즉, 메소드 포인터는 두 개의 주소를 저장한다.

 

그것은 메소드 코드의 주소와 객체 인스턴스의 주소이다.

객체 인스턴스의 주소는 메소드 내부에서 self로서 나타난다.

 

type

  TestProc = procedure (Param: Integer) of object;

 

이렇게 선언이 되었다면 객체 안에서 메소드 포인터 형을 가질 수 있다.

 

type

  MyClass1 = class

  Proc1: TestProc;

end;

 

그러면 나중에 이 필드와 같은 종류이며 같은 데이터 형의 파라미터를 갖는

어떤 메소드(프로시저 혹은 함수)이든 대입할 수 있다.

 

type

  MyClass2 = class

  procedure DoubleProc(Value: Integer);

end;

 

이렇게 또다른 클래스에서 DoubleProc이라는 프로시저를 선언했다고 하자.

이것은 같은 종류이면서 같은 정수형의 파라미터를 갖는다.

 

var

  My1: MyClass1;

  My2: MyClass2;

 

다음과 같이 선언한다면

 

My1.Proc1 := My2.DoubleProc;

 

위와 같이 할당을 할 수 있으며

 

My1.Proc1;

 

이렇게 호출하는 것은 My2의 DoubleProc을 호출하는 것과 같다.

이것은 VCL의 기본 구조 중의 하나이다.

 

이에 대한 궁금증을 해소하기 위해 실제 VCL에서 어떻게 구현되고

사용되는지 알아보자.

 

Button 컴포넌트의 OnMouseDown 이벤트를 예로 하자.

이외의 대부분의 경우도 모두 갑은 구조임을

소스 파일을 열어 봄으로써 확인할 수 있을 것이다.

 

TButton의 상속 구조를 따라가면

Button의 OnMouseDown 이벤트는 TControl에 정의되어 있음을 알 수 있다.

 

FOnMouseDown: TMouseEvent;

property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;

 

여기서 OnMouseDown 프로퍼티는 TMouseEvent

메소드 포인터 형의 변수로 선언되어져 있다.

 

type

TMouseEvent = procedure(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) of object;

 

TMouseEvent는 위에서 보는 바와 같이

classes.pas에서 메소드 포인터로 선언되어져 있다.

 

따라서, Object Inspector의 Events 페이지에 나타나는

이벤트는 사실 메소드 포인터 형의 property일 뿐이다.

 

그럼 델파이에서 새로이 Application을 생성하고

폼 위에 버튼을 하나 올려놓자.

 

그리고 나서 Object Inspector의 Events 페이지에

OnMouseDown을 두번 클릭하면

 

procedure Button1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

 

이 생성된다.

 

우리가 할 일은 implement 아래에서 Botton1MouseDown에 구현하고자 하는 소스를 코딩하면 된다.

 

type

  TForm1 = class(TForm)

    Button1: TButton;

    procedure Button1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

  private

    { Private declarations }

  public

    { Public declarations }

end;

 

procedure Button1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin

  // 하고자 하는 소스 코드

end;

 

이것은 Button1의 OnMouseDown은 property로 선언되어져 있으므로

명시적으로 할당하지는 않았지만 내부적으로

 

Button1.OnMouseDown := Form1.Button1MouseDown;

 

이 할당되는 것으로 볼 수 있다. (* 이 부분은 검증되지 않았으며 개인적인 생각임.)

 

OnMouseDown은 property 이름이며

실제 가리키는 데이터는 TControl의 private 형으로 선언된 FOnMouseDown이다.

 

또한 같은 종류이며 같은 데이터 형을 파라미터로 가지는

OnMouseUp 이벤트 핸들러의 경우 TMouseEvent 메소드 포인트 형을 이용하여

OnMouseUp 이벤트 핸들러를 추가시킬 수 있다.

 

procedure Button1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

 

여기까지가 메소드 포인터에 대한 간략한 설명이었다.

더 자세한 내용은 다음 기회에 실제 구현된 소스와 함께 다루도록 하자.

 

클래스 레퍼런스 (Class Reference)

: 참고로 클래스 레퍼런스도 공부해 보길 바란다.

 

간단히 설명하자면 클래스 형에 대한 레퍼런스를 뜻하며 클래스 레퍼런스는

클래스 데이터 형을 실행 도중에 조작할 수 있도록 한다.

 

델파이의 런타임 라이브러리와 VCL 안에서 많이 볼 수 있을 것이다.

형식은 다음과 같다.

 

TClass = class of TObject;

 

가장 흔히 보는 TForm 클래스의 선언부 아래에도 보면

 

TFormClass = class of TForm;

 

이라는 클래스 레퍼런스가 선언되어져 있음을 볼 수 있다.

 

728x90
반응형

'Delphi > 문법' 카테고리의 다른 글

상속(inheritance)과 연결(association)  (0) 2024.04.08
델파이 추상화(abstraction)  (0) 2024.03.26
델파이 동적 2차원 배열  (0) 2023.09.25
델파이 Parameter  (0) 2023.09.22
델파이 Application  (0) 2023.09.21

댓글