메소드의 내부 표현

Objective-C 컴파일러는, 메소드를 특정하는 이름을 컴파일시에 내부 표현으로 변환합니다. 이, 메소드의 내부 표현을 셀렉터라고 부르고, 메세지의 송수신의 뒤편에서는, 이 셀렉터가 교환되고 있습니다. 메소드를 특정하기 위한 내부 표현에 대해서는 컴파일러에 의존하는 문제이며, 개발자가 알아야 할 범위가 아닙니다. 개발자에게 있어서 중요한 것은, 이 셀렉터를 SEL 형태로서 취급할 수 있다고 하는 사실입니다.

메소드가 어떠한 데이터에 변환되어 어떻게 식별되고 있는가는 문제가 아닙니다. 그러나, Objective-C는 이 내부 표현을 SEL 형태의 변수로서 취급하는 것을 보장하고 있습니다. 즉, SEL 형태의 변수에는, 메소드명을 식별하기 위해서 컴파일러가 할당한 특수한 코드를 보존할 수 있는 것이 됩니다.

메소드를 특정하는 실렉터는 @selector 컴파일러 지시문을 이용해 취득할 수 있습니다.

@selector ( method )

method 에는, 실렉터를 취득하고 싶은 메소드의 이름을 지정합니다. 지정한 메소드의 이름이 존재할지 어떨지는, 메소드를 호출할 때, 실행시에 판정되기 위해, 컴파일시에는 평가되지 않을 것입니다.

그럼, 취득한 실렉터의 값을 SEL 형태의 변수에 보존했다고 해서, 이것을 어떻게 이용할 수 있는 것입니까. 셀렉터가 메소드를 특정한다고 하는 성질이 있는 이상, 역시 최대의 이용 방법은, 함수에의 포인터와 같이, 동적으로 메소드를 특정하는 방법이지요. 셀렉터로부터 메소드를 호출하는 기능을 제공하는 것은 루트 클래스입니다.

Object 클래스에는, SEL 형태의 값을 받는 perform 메소드가 선언되고 있습니다. 이 메소드는, 인수로 받은 실렉터가 특정하는 메소드를 실행합니다.

- perform:(SEL)aSel;

- perform:(SEL)aSel with:anObject;

- perform:(SEL)aSel with:anObject1 with:anObject2;

aSel 에 호출하는 메소드의 셀렉터를 지정합니다. anObject,anObject1,anObject2 에는 메소드에 건네주는 인수를 지정할 수 있습니다.

#import <stdio.h>
#import <objc/Object.h>

@interface Test : Object
- (void)Write;
@end

@implementation Test
- (void)Write {
	printf("I am the bone of my sword.\n");
}
@end

int main() {
	id obj;
	SEL method;

	obj = [Test new];
	method = @selector(Write);
	[obj perform:method];

	return 0;
}

이 프로그램에서는, Write 메소드를 나타내는 실렉터를 SEL 형태의 변수 method 에 보존하고 있습니다. 그리고,Test 클래스의 인스턴스 obj 에 perform 메세지를 method를 인수로서 송신합니다. perform 메소드는, 주어진 실렉터로부터 실행해야 할 메소드를 산출해 실행합니다. 이 성질을 능숙하게 이용하면, 실행시에 호출해야 할 메소드를 상황에 따라 바꾸는 프로그램을 실현할 수 있습니다.

Posted by tklee