Objective-C에서 슈퍼와self에 대한 이해
슈퍼: 컴파일러 지시자일 뿐 바늘이나 대상이 아닙니다. 현재 대상이 부모 클래스를 호출하는 방법인self를 표시합니다. 실례적인 방법의self는 대상의 첫 번째 주소이고 클래스 방법의self는Class입니다.
2. 관련 용법과 차이
우선 두 가지 클래스인 ClassA, ClassB를 만들고 ClassB가 ClassA를 계승하도록 하겠습니다.
@interface ClassA : NSObject
- (void)classAMethod;
@end
#import "ClassA.h"
@implementation ClassA
- (void)classAMethod{
NSLog(@" ClassA ");
}
@end
#import "ClassA.h"
@interface ClassB :ClassA
- (void)classBMethod;
- (void)test;
@end
#import "ClassB.h"
@implementation ClassB
- (instancetype)init {
self = [super init];
if (self){
}
return self;
}
- (void)classBMethod {
NSLog(@"[super class] == %@",[super class]);
NSLog(@"[self class] == %@",[self class]);
NSLog(@"[self superclass] == %@",[self superclass]);
NSLog(@"[super superclass] == %@",[super superclass]);
}
- (void)classAMethod {
NSLog(@" ClassB ");
}
- (void)test{
[self classAMethod];
[super classAMethod];
}
@end
ViewController에서 ClassB의 실례를 초기화하고classBMethod 방법을 호출하여 다음 결과를 얻습니다
- (void)viewDidLoad {
[super viewDidLoad];
ClassB *instanceB = [[ClassB alloc] init];
[instanceB classBMethod];
}
2018-07-04 14:23:20.072983+0800 OCCodeDemo[73161:3730280] [super class] == ClassB
2018-07-04 14:23:20.073119+0800 OCCodeDemo[73161:3730280] [self class] == ClassB
2018-07-04 14:23:20.073237+0800 OCCodeDemo[73161:3730280] [self superclass] == ClassA
2018-07-04 14:23:20.073358+0800 OCCodeDemo[73161:3730280] [super superclass] == ClassA
우리는 [슈퍼 클래스]와 [self 클래스]가 얻은 결과가 똑같다는 것을 알 수 있다. 모두 현재 클래스 클래스 클래스를 가리키고, [self 슈퍼 클래스]와 [슈퍼 슈퍼 클래스]는 모두 부모 클래스 클래스 클래스를 가리키고, 우리는 클래스 B를 가리킨다.m 파일을 실행할 때의 코드로 컴파일합니다. 다음은classBMethod 방법으로 실행할 때의 코드입니다.
static void _I_ClassB_classBMethod(ClassB * self, SEL _cmd) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_ps_vpyt2wb51qqcqlxlfqlntnmw0000gn_T_ClassB_942b53_mi_0,((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ClassB"))}, sel_registerName("class")));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_ps_vpyt2wb51qqcqlxlfqlntnmw0000gn_T_ClassB_942b53_mi_1,((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class")));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_ps_vpyt2wb51qqcqlxlfqlntnmw0000gn_T_ClassB_942b53_mi_2,((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("superclass")));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_ps_vpyt2wb51qqcqlxlfqlntnmw0000gn_T_ClassB_942b53_mi_3,((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ClassB"))}, sel_registerName("superclass")));
}
메시지를 볼 수 있는 수신자는self, 즉 대상instanceB(class와 슈퍼클래스는 모두 NSObject 클래스의 내부 함수) 여기의selregisterName 공식 정의는 Registers a method with the Objective-C runtime system, maps the method name to a selector, and returns the selector value입니다. 즉, 방법을 런타임 시스템에 등록하고 방법 이름과 selector를 비추어 selector의 값을 되돌려줍니다.
다음에 테스트 방법을 사용해서 다음 결과를 얻었습니다.
2018-07-04 15:07:49.387521+0800 OCCodeDemo[74261:3766110] ClassB
2018-07-04 15:07:49.387635+0800 OCCodeDemo[74261:3766110] ClassA
만약 우리가classB의classamethod방법을 제거하면, 다음에 테스트 방법을 호출하면 다음과 같은 결과를 얻을 수 있다
2018-07-04 15:21:52.620538+0800 OCCodeDemo[74537:3777302] ClassA
2018-07-04 15:21:52.620654+0800 OCCodeDemo[74537:3777302] ClassA
이러한 결과가 나타나는 주요 원인은 ObjectIve-C에서runtime 메시지 메커니즘과 관련이 있으며, [self classamethod]는 컴파일러에 의해 objc 로 전환됩니다.msgSend(self, @selector(classAMethod)), [super classamethod]가 컴파일러에 의해 objcmsgSendSuper(self,classamethod),self는 본 클래스의 IMP를 먼저 찾고 대응하는 함수를 찾으면 실행한다. 찾지 못하면 부류/초류에서 찾는다. 슈퍼는 부류에서 먼저 찾고 대응하는 함수를 찾아 실행한다. 찾지 못하면 부류/초류로 계속 찾는다. 그러나 메시지를 받는 대상은 모두self이다. 왜self인지는 실행 코드를 살펴보자.메시지를 받을 수 있는 대상은self입니다.
static void _I_ClassB_test(ClassB * self, SEL _cmd) {
((void (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("classAMethod"));
((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ClassB"))}, sel_registerName("classAMethod"));
}
이상의 예는 슈퍼가 컴파일 표식자로서 현재 대상을 표시하고 부류를 호출하는 방법을 잘 설명하지만 메시지를 받는 것은 현재 대상이다
다음은 self = [super init]
[super init]에 대해서는 다들 잘 알고 있지만 [super init] 이후에 왜 self에 값을 부여했는지 NSObject를 살펴보자.m의 init 방법 실현
- (id)init {
return _objc_rootInit(self);
}
id
_objc_rootInit(id obj)
{
// In practice, it will be hard to rely on this function.
// Many classes do not properly chain -init calls.
return obj;
}
런타임 코드로 전환하려면 다음과 같이 하십시오.
static instancetype _I_ClassB_init(ClassB * self, SEL _cmd) {
self = ((ClassB *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ClassB"))}, sel_registerName("init"));
if (self){
}
return self;
}
실행 중인 코드에서 알 수 있듯이 [super init]는 최종적으로classB의 실례 대상을 되돌려주고self에 값을 부여한다
3. 총결산
이 글은 단지 관건적인 문자 슈퍼의 정의와 작용, 그리고 시스템이 운행할 때self와의 관계를 소개했을 뿐,self에 대해 더 상세한 연구를 하지 않았으며, 부족한 점이 있으면 바로잡아 함께 학습하고 진보하도록 하였다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.