標籤:
super
在Objective-C中,如果我們需要在類的方法中調用父類的方法時,通常都會用到super,如下所示:
@interface MyViewController: UIViewController @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; // do something ...} @end
如何使用super我們都知道。現在的問題是,它是如何工作的呢?
首先我們需要知道的是super與self不同。self是類的一個隱藏參數,每個方法的實現的第一個參數即為self。而super並不是隱藏參數,它實際上只是一個”編譯器標示符”,它負責告訴編譯器,當調用viewDidLoad方法時,去調用父類的方法,而不是本類中的方法。而它實際上與self指向的是相同的訊息接收者。為了理解這一點,我們先來看看super的定義:
struct objc_super { id receiver; Class superClass; };
這個結構體有兩個成員:
receiver:即訊息的實際接收者
superClass:指標當前類的父類
當我們使用super來接收訊息時,編譯器會產生一個objc_super結構體。就上面的例子而言,這個結構體的receiver就是MyViewController對象,與self相同;superClass指向MyViewController的父類UIViewController。
接下來,發送訊息時,不是調用objc_msgSend函數,而是調用objc_msgSendSuper函數,其聲明如下:
id objc_msgSendSuper ( struct objc_super *super, SEL op, ... );
該函數第一個參數即為前面產生的objc_super結構體,第二個參數是方法的selector。該函數實際的操作是:從objc_super結構體指向的superClass的方法列表開始尋找viewDidLoad的selector,找到後以objc->receiver去調用這個selector,而此時的操作流程就是如下方式了。
objc_msgSend(objc_super->receiver, @selector(viewDidLoad))
由於objc_super->receiver就是self本身,所以該方法實際與下面這個調用是相同的:
objc_msgSend(self, @selector(viewDidLoad))
為了便於理解,我們看以下執行個體:
@interface MyClass : NSObject @end @implementation MyClass - (void)test { NSLog(@"self class: %@", self.class); NSLog(@"super class: %@", super.class);} @end
調用MyClass的test方法後,其輸出是:
2015-06-13 15:55:03.256 [824:209297] self class: MyClass2015-06-13 15:55:03.256 [824:209297] super class: MyClass
從上例中可以看到,兩者的輸出都是MyClass。大家可以自行用上面介紹的內容來分析一下。
理解Objective-C Runtime (六)super