Malcolm T.Gladwell說(shuō):“人們眼中的天才之所以卓越非凡险绘,并非天資超人一等,而是付出了持續(xù)不斷的努力。1萬(wàn)小時(shí)的錘煉是任何人從平凡變成超凡的必要條件帆疟。”
對(duì)于一萬(wàn)小時(shí)定律宇立,我是深信不疑的踪宠,然而真的嘗試做著的時(shí)候,才發(fā)現(xiàn)一萬(wàn)小時(shí)妈嘹,對(duì)于天資愚鈍的我還遠(yuǎn)遠(yuǎn)不夠柳琢。
學(xué)習(xí)Objective-C已近兩年,每天的工作學(xué)習(xí)的平均時(shí)間也控制在十個(gè)小時(shí)以上润脸,漸漸地一直以為自己對(duì)其機(jī)制及語(yǔ)法有了一定認(rèn)識(shí)柬脸,然而看到別人對(duì)兩個(gè)編程中最常用到關(guān)鍵字self、super的理解的時(shí)候毙驯,實(shí)在羞愧倒堕,深感自己對(duì)平日使用的東西了解還太少太少。
正文
當(dāng)然爆价,這一切都要從一個(gè)Model和一個(gè)網(wǎng)上的筆試題說(shuō)起:
1垦巴、一個(gè)Model
#import <Foundation/Foundation.h>
@interface EVNHelper : NSObject
- (instancetype)init;
@end
#import "EVNHelper.h"
@implementation EVNHelper
- (instancetype)init
{
self = [super init];// ?允坚?魂那?
if (self)
{
// other init code
}
return self;
}
@end
2、 一個(gè)筆試題
- (instancetype)init
{
self = [super init];
if (self)
{
NSLog(@"self className is %@", NSStringFromClass([self class]));
NSLog(@"super className is %@", NSStringFromClass([super class]));
NSLog(@"self superclass className is %@", NSStringFromClass([self superclass]));
NSLog(@"super superclass className is %@", NSStringFromClass([super superclass]));
}
return self;
}
@end
輸出:
2016-12-24 16:04:32.600 Demo[6009:1006834] self className is EVNHepler
2016-12-24 16:04:32.601 Demo[6009:1006834] super className is EVNHepler
2016-12-24 16:04:32.601 Demo[6009:1006834] self superclass className is NSObject
2016-12-24 16:04:32.602 Demo[6009:1006834] super superclass className is NSObject
對(duì)應(yīng)的問(wèn)題也來(lái)了:
1稠项、子類初始化為什么要寫self = [super init]涯雅,意義?
2展运、為什么[self class]和 [super class]活逆;[self superclass]和[super superclass]輸出相同精刷?
可到底self和super是什么呢?(由于對(duì)runtime懂得太少蔗候,怕誤人子弟怒允,暫不扯底層代碼,只說(shuō)自己能看到的)
-
self
之前我的理解锈遥,self是對(duì)象指針纫事,指向當(dāng)前類的實(shí)例對(duì)象。其實(shí)這種理解是不準(zhǔn)確的所灸,因?yàn)樵陟o態(tài)方法self 依然可以使用(如下代碼)丽惶,這怎么解釋呢!
+ (void)helperMethodA
{
[self helperMethodB];
}
+ (void)helperMethodB
{
NSLog(@"asdfasdfasd");
}
帶著這份好奇爬立,最終我在NSObject
協(xié)議中找到了self钾唬,原來(lái)self是返回instancetype類型的代理方法,但又有些奇怪侠驯,我們?cè)谧远x子類的時(shí)候并沒(méi)有實(shí)現(xiàn)這個(gè)方法抡秆,我認(rèn)為self的功能,OC已經(jīng)幫我們實(shí)現(xiàn)吟策,只是我們看不到而已儒士。這樣就明確了,self最終返回的結(jié)果就是instancetype類型的東西檩坚,它是動(dòng)態(tài)類型乍桂,最終運(yùn)行時(shí)才會(huì)確定,實(shí)例方法返回實(shí)例類型效床、靜態(tài)方法返回的是Class睹酌。
#include <objc/objc.h>
#include <objc/NSObjCRuntime.h>
@class NSString, NSMethodSignature, NSInvocation;
@protocol NSObject
- (BOOL)isEqual:(id)object;
@property (readonly) NSUInteger hash;
@property (readonly) Class superclass;
......
- (Class)class OBJC_SWIFT_UNAVAILABLE("use 'anObject.dynamicType' instead");
- (instancetype)self;
......
@end
-
super
在Foundation框架中,super是找不到的剩檀,該關(guān)鍵字應(yīng)該是比self更為奇特的東西憋沿。雖然找不到super,但我們可以看到結(jié)構(gòu)體objc_super
沪猴,在官方解釋中我們能看到一些端倪辐啄。
objc_super: The compiler generates an objc_super data structure when it encounters the super keyword as the receiver of a message. It specifies the class definition of the particular superclass that should be messaged.
大致意思就是,當(dāng)遇到super關(guān)鍵字時(shí)运嗜,編譯器會(huì)生成一個(gè)objc_super結(jié)構(gòu)體壶辜,作為消息的接收者,objc_super結(jié)構(gòu)體使得接收消息的父類的定義被明確化担租。
所以砸民,super的含義應(yīng)該是一種編譯指令,它的作用用來(lái)給父類發(fā)送消息,并返回消息響應(yīng)的結(jié)果岭参。
#include <objc/objc.h>
#include <objc/runtime.h>
#pragma GCC system_header
#ifndef OBJC_SUPER
#define OBJC_SUPER
/// Specifies the superclass of an instance.
struct objc_super {
/// Specifies an instance of a class.
__unsafe_unretained id receiver;
/// Specifies the particular superclass of the instance to message.
#if !defined(__cplusplus) && !__OBJC2__
__unsafe_unretained Class class;
#else
__unsafe_unretained Class super_class;
#endif
};
知悉了這兩點(diǎn)反惕,上面的兩個(gè)問(wèn)題也就迎刃而解了。
解答:
問(wèn)題一:self = [super init]是面向?qū)ο笏枷氲囊环N體現(xiàn)演侯,意義就是姿染,利用父類的init方法為子類初始化父類的公有屬性。
問(wèn)題二:理解這個(gè)先要明確alloc和init的區(qū)別秒际,alloc為對(duì)象開辟內(nèi)存悬赏,init是對(duì)象初始化,所以娄徊,[super init] 是初始化在子類上的舷嗡,super發(fā)出消息的主體對(duì)象是子類,和self是同一個(gè)對(duì)象嵌莉。 class方法和self類似是NSObject協(xié)議中的代理方法,我認(rèn)為class的功能捻脖,OC也已經(jīng)幫我們實(shí)現(xiàn)在每個(gè)子類中锐峭,只是我們看不到而已,所以不管是super還是self發(fā)出的class消息可婶,執(zhí)行的時(shí)候沿癞,都在子類中,返回的都是子類矛渴。