메소드의 덧쓰기

클래스의 계승으로 특필해야 하는 것은, 단순한 기능의 계승이 아닙니다. 클래스의 계승은 추상적인 기능을 구체적인 처리로 이행하는, 기능의 덧쓰기에 있다고 생각할 수 있습니다. 이, 기능의 덧쓰기란, 슈퍼 클래스의 메소드를 은폐 해, 서브 클래스의 메소드를 우선적으로 호출하게 하는, 메소드의 덧쓰기에 의해서 실현됩니다. 이것을, 일반적으로는오버라이드(override)라고 부릅니다.

메소드의 오버라이드(override)는, 슈퍼 클래스의 메소드와 같은 이름, 같은 반환값형, 같은 인수의 메소드를 서브 클래스에서 정의하는 것으로 실현됩니다. 일반적으로는, 이러한 메소드명과 메소드의 반환값이나 인수형 전체를 서명이라고 부릅니다. 메소드의 오버라이드(override)는, 서명이 같은 메소드를 서브 클래스에서 정의하는 것으로 실현됩니다.

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

@interface SuperClass : Object
- (void)method;
@end

@interface SubClass : SuperClass
-(void)method;
@end

@implementation SuperClass
- (void)method {
	printf("SuperClass.method\n");
}
@end

@implementation SubClass
- (void)method {
	printf("SubClass.method\n");
}
@end

int main() {
	[[SuperClass alloc] method];
	[[SubClass alloc] method];
	return 0;
}

이 프로그램에서는, 슈퍼 클래스인 SuperClass 클래스와 서브 클래스인 SubClass 클래스에서 서명이 동일한 method 메소드를 선언, 및 정의하고 있습니다. Objective-C는 이러한 메소드의 충돌은 compile error가 아닌, 메소드의 덧쓰기, 즉 오버라이드(override) 하는 것으로 해결합니다.

오버라이드(override) 된 메소드의 효과는 main() 메소드의 실행 결과를 보면 확인할 수 있습니다. 인스턴스가 SuperClass 의 경우는 SuperClass 클래스의 method 메소드가 불려지며 인스턴스가 SubClass 클래스의 것이면 SubClass 의 method 메소드가 불려 집니다. 이것은 SubClass가 SuperClass 의 method 메소드를 숨겨, 새롭게 정의한 스스로의 method 메소드로 오버라이드(override) 한 것을 나타냅니다.

오버라이드(override)는, 결과적으로 프로그램의 다양성을 실현합니다. 메소드를 호출하는 코드는, 코드를 변경하지 않아도, 인스턴스에 의해서 호출해야 할 적절한 메소드를 선택할 수 있게 됩니다. 다음과 같은 코드를 상정해 주세요.

void CallMethod(id obj) {
	[obj method];
}

int main() {
	CallMethod([SuperClass alloc]);
	CallMethod([SubClass alloc]);

	return 0;
}

이 코드에서는, CallMethod() 함수로 id 형태의 오브젝트를 인수로부터 받고 있습니다. 이 함수에서는, 받은 오브젝트의 method 메소드를 호출하고 있습니다.

그러나, 이 함수가 결과적으로 어느 메소드를 호출할까는, 건네받는 오브젝트의 인스턴스에 따라서 다릅니다. 함수가 호출하는 메소드는, 실행시기가 아니면 최종적인 판정은 할 수 없습니다. C 언어에서는,switch 문장등에서 분기 시켜 호출해야 할 함수를 선별하거나 실행시에 동적으로 함수를 호출하는 구조를 실현하기 위해서, 함수에의 포인터등을 이용하지 않으면 안됩니다. Objective-C는 그러한 독자적인 설계는 필요없고, 동적인 호출에 의한 코드의 다양성을 언어 레벨로 서포트하고 있습니다.

그런데 , 슈퍼 클래스의 메소드가 완전하게 은폐 되어도 곤란한 일이 있습니다. 특히, 메소드의 오버라이드(override)의 목적이 기능의 확장인 경우, 확장하는 부분만큼을 서브 클래스에서 기술해, 나머지의 기본적인 처리 부분은 슈퍼 클래스의 오버라이드(override) 된 메소드에 맡겨야 합니다. 이것을 실현하려면 , 서브 클래스의 오버라이드(override) 한 메소드로부터, 슈퍼 클래스의 오버라이드(override) 된 메소드를 호출할 필요가 있습니다.

슈퍼 클래스의 메소드를 서브 클래스로부터 명시적으로 호출하려면 super 를 이용합니다. super 는,슈퍼 클래스를 보유하는 클래스의 인스턴스 메소드내의 메세지에서만 이용할 수 있는 특별한 이름으로, 슈퍼 클래스의 메소드를 호출하는 것을 명시합니다. self 는 인스턴스 메소드내에 존재하는 암묵적인 id 형태의 변수였지만, super 는 변수는 아닌 것에 주의해 주세요.

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

@interface SuperClass : Object
{
	int x;
}
- (void)method;
@end

@interface SubClass : SuperClass
-(void)method;
@end

@implementation SuperClass
- (void)method {
	printf("SuperClass.method\n");
}
@end

@implementation SubClass
- (void)method {
	printf("SubClass.method %d\n" , x);
	[super method];
}
@end

int main() {
	[[SubClass alloc] method];
	return 0;
}

이 프로그램에서는 SuperClass 의 메소드를 오버라이드(override) 하고 있는 SubClass 의 method 메소드로부터, 슈퍼 클래스의 오버라이드(override) 된 method 메소드를 호출하기 위해서 super 를 이용하고 있습니다. 실행 결과로부터, SubClass 의 method 로부터 SuperClass 의 method를 호출하고 있는 것을 확인할 수 있겠지요.


Posted by tklee

댓글을 달아 주세요