簡體   English   中英

在Objective-C中了解超級

[英]Understanding super in 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

`

當我調用test方法時,我希望看到父類已打印並執行了父whoAmI方法。 但是令人驚訝的是,兩次都調用了派生類。 誰能解釋為什么會發生以及如何在基類上執行performSelector:

super方法只是將消息轉發到超類的實現代碼的一種方式。 但是, self保持不變。 實際上,如果創建Child的實例,則根本沒有Parent實例。 您可以通過NSLog-ing self作為%p進行測試,以檢查指針地址; 當調用super方法時, self指針與調用它的子類的實例相同:

上級:

- (void)printAddr {
    NSLog(@"%p", self);
}

兒童:

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

如果調用[aChild printAddr];您將看到指針相同[aChild printAddr];

現在,讓我們將其轉化為解決您的特定問題。 首先,看一下performSelector:方法。 它的默認實現在NSObject中,並且該實現很可能使用self來調用選擇器。 因此,即使方法實現是NSObject的實現,該方法仍將在實際對象(子類)上調用。 如果不是這種行為,那么performSelector:總是會嘗試調用該方法,就像直接在NSObject上實現一樣,除非您在子類上實現了自己的performSelector:; 顯然,這是錯誤的行為。

此外, -class方法也適用。 它的默認實現駐留在NSObject上,並且很明顯它總是返回[NSObject class] ,所以很無聊,因此它有效地使用self來獲取真實對象的類。

您還可以通過在超類上創建一個方法來測試我在這里所說的話,該方法在self上調用另一個方法。 即使您使用super來調用第一個方法,由於self仍指向子類,因此第二個方法仍將在子類上被調用:

上級:

- (void)method {
    NSLog(@"Parent: method");
    [self method1];
}
- (void)method1 {
    NSLog(@"Parent method1");
}

兒童:

- (void)method {
    [super method];
}
- (void)method1 {
    NSLog(@"Child: method1");
}

在這種情況下, [aChild method]將輸出:

Parent: method
Child: method1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM