Objective-C에서 슈퍼와self에 대한 이해

5625 단어
설명
슈퍼: 컴파일러 지시자일 뿐 바늘이나 대상이 아닙니다. 현재 대상이 부모 클래스를 호출하는 방법인self를 표시합니다. 실례적인 방법의self는 대상의 첫 번째 주소이고 클래스 방법의self는Class입니다.
2. 관련 용법과 차이
  • [super class]
  • [self class]
  • [self superclass]
  • [super superclass]
  • self = [super init]

  • 우선 두 가지 클래스인 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에 대해 더 상세한 연구를 하지 않았으며, 부족한 점이 있으면 바로잡아 함께 학습하고 진보하도록 하였다.

    좋은 웹페이지 즐겨찾기