[英]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.