클래스 상속에서 주목할만한 것은 단순한 기능의 상속이 없습니다. 클래스의 상속은 추상적 인 기능을 구체적인 처리로 전환하는 기능 재정에 있다고 생각합니다. 이 기능 덮어 쓰기는 슈퍼 클래스의 메소드를 은폐하고 서브 클래스의 메소드를 우선 낮은 호출하는 메소드의 재정의를 통해 제공합니다. 이것을 일반적으로 재정 라고합니다.
메소드의 오버라이드 (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에서는 이러한 메소드의 충돌은 컴파일 오류가 아닌 메소드 재정, 즉 무시할에서 해결합니다.
재정의 된 메소드의 효과는 main () 메소드의 실행 결과를 보면 확인 할 수 있습니다. 인스턴스가 SuperClass의 경우는 SuperClass 클래스의 method 메소드를 호출하여 인스턴스가 SubClass 클래스의 것이면 SubClass의 method 메소드가 불려갑니다. 이것은 SubClass가 SuperClass의 method 메소드를 숨겨, 새롭게 정의한 스스로의 method 메소드로 대체 한 것을 나타냅니다.
우선은 결과적으로 프로그램의 다양성을 제공합니다. 메소드를 호출하는 코드는 코드를 변경하지 않고도 인스턴스에 의해 호출 할 적절한 방법을 선택할 수있게 될 것입니다. 다음과 같은 코드를 상정합니다.
void CallMethod(id obj) {
[obj method];
}
int main() {
CallMethod([SuperClass alloc]);
CallMethod([SubClass alloc]);
return 0;
}
이 코드는 CallMethod () 함수에서 id 형식의 객체를 인수로 받고 있습니다. 이 함수는받은 객체의 method 메소드를 호출합니다.
그러나이 함수가 결과적으로 어떤 메소드를 호출하는지는 전달되는 개체의 인스턴스에 따라 달라집니다. 함수가 호출 메서드는 런타임이되어야 최종 판정은 할 수 없습니다. C 언어에서는 switch 문 등으로 분기시켜 호출 할 함수를 가리고 런타임에 동적으로 함수를 호출하는 구조를 실현하기 위해 함수 포인터 등을 이용해야 없습니다. Objective-C에서는 이러한 독특한 설계는 필요없이 동적 호출하여 코드의 다양성을 언어 차원에서 지원하고있는 것입니다.
그런데 슈퍼 클래스의 메소드가 완전하게 은폐되어도 곤란 수 있습니다. 특히 메서드 재정의 목적이 기능의 확장 인 경우 확장 부분을 서브 클래스로 작성하고 나머지 기본적인 처리 부분은 슈퍼 클래스의 재정의 된 메소드에 맡겨야합니다. 이것을 실현하려면 서브 클래스의 재정의 한 메소드에서 슈퍼 클래스의 재정의 된 메서드를 호출해야합니다.
슈퍼 클래스의 메소드를 서브 클래스에서 명시 적으로 호출하려면 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 메소드에서 슈퍼 클래스의 재정의 된 method 메소드를 호출하기 전에 super를 이용하고 있습니다. 실행 결과에서 SubClass의 method에서 SuperClass의 method를 호출하는 것을 확인할 수있을 것입니다.