理解客观的超级c

And*_*kha 1 inheritance objective-c

请考虑以下代码:

  `@interface Parent : NSObject

    - (void)whoAmI;

   @end

   @implementation Parent

   - (void)whoAmI
   {
     NSLog(@"PARENT CALLED");
   }

   @end

   @interface Child : Parent

   - (void)test;

   @end

   @implementation Child

   - (void)whoAmI
   {
      NSLog(@"CHILD CALLED");
   }

   - (void)test
  {
      NSLog(@"%@", [super class]);// CHILD!!!! why???
     [super performSelector:@selector(whoAmI)];// "CHILD CALLED" why???
  }

  @end
Run Code Online (Sandbox Code Playgroud)

`

当我调用test方法时,我希望看到父类打印并whoAmI执行父方法.但令人惊讶的是,两次派生类都被调用.任何人都可以解释它为什么会发生,我如何performSelector:在基类?

Ale*_*hol 5

super方法只是一种将消息转发到超类的实现代码的方法.但是,self保持不变.实际上,如果您创建一个实例Child,则根本没有实例Parent.您可以通过NSLog的-ING测试此self作为%p检查指针地址; 当调用super方法时,self指针与调用它的子类实例的指针相同:

家长:

- (void)printAddr {
    NSLog(@"%p", self);
}
Run Code Online (Sandbox Code Playgroud)

儿童:

- (void)printAddr {
    NSLog(@"sub: %p, self");
    [super printAddr];
}
Run Code Online (Sandbox Code Playgroud)

如果你打电话,你会看到指针是相同的[aChild printAddr];.

现在让我们将其转化为解决您的具体问题.首先,看看performSelector:方法.它的默认实现是在NSObject中,这个实现很可能用于self调用选择器.因此,即使方法实现是NSObject的方法实现,仍然会在真实对象(您的子类)上调用该方法.如果不是这种行为,performSelector:总是会尝试调用该方法,就好像它是直接在NSObject上实现的,除非你在子类上实现了自己的performSelector:显然,这是错误的行为.

另外,对于该-class方法也是如此.它的默认实现驻留在NSObject上,显然它总是会返回无聊的id [NSObject class],所以它实际上用它self来获取真实对象的类.

您还可以通过在超类上调用另一个方法来测试我在这里所说的内容self.即使您使用super第一个方法调用,第二个方法仍将在您的子类上调用,因为self仍然指向子类:

家长:

- (void)method {
    NSLog(@"Parent: method");
    [self method1];
}
- (void)method1 {
    NSLog(@"Parent method1");
}
Run Code Online (Sandbox Code Playgroud)

儿童:

- (void)method {
    [super method];
}
- (void)method1 {
    NSLog(@"Child: method1");
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,[aChild method]将输出:

Parent: method
Child: method1
Run Code Online (Sandbox Code Playgroud)