day23 self 與 super , 父類調(diào)用子類方法 ---- iOS

day23

1.self 與 super , 父類調(diào)用子類方法

1.1 self 與 super

前面也寫(xiě)到了self 與 super 的區(qū)別,在 OC Examination 那天中.
內(nèi)容如下:

不管是 self  還是 super 其消息主體依然是  self   ,也就是說(shuō) self 和 super 指向的
是同一個(gè)對(duì)象迫卢。只是 查找方法的位置 區(qū)別串述,一個(gè)從本類,一個(gè)從本類的超類够挂。

其實(shí)這段話是從網(wǎng)上找的,其含義并不是太明白.

    - 為什么self和super指向的依舊是self本身?
      記得好像其它語(yǔ)言中,self指向的就是本類,而super指向的就是父類.
    - 為什么self和super要這樣去定義?

1.2 initWithFrame: 方法

今天學(xué)習(xí)的是關(guān)于自定義控件, 自定義控件時(shí)一般都需要重寫(xiě)構(gòu)造方法來(lái)初始化該控件中的子控件,這時(shí)候最先想到的就是重寫(xiě)init方法,在init中創(chuàng)建子控件,初始化等操作.這樣創(chuàng)建控件的時(shí)候,調(diào)用init方法就好了.這樣確實(shí)可以做到.但是有人在創(chuàng)建控件時(shí)還想把控件里需要的參數(shù)傳遞進(jìn)去,于是再定義一個(gè)" - (instancetype)initWithShop:(XMGShop *)shop " 方法. 或者定義一個(gè)類工廠方法 "+ (instancetype)shopViewWithShop:(XMGShop *)shop". 一運(yùn)行,結(jié)果什么控件也看不到.因?yàn)樯鲜龅膬蓚€(gè)方法不會(huì)來(lái)到init方法,不會(huì)去創(chuàng)建子控件,所以你什么也看不到.

這時(shí)候有人會(huì)告訴你" 添加子控件,做初始化的設(shè)置,init方法內(nèi)部會(huì)調(diào)用initWithFrame, 所以你只需要重寫(xiě)initWithFrame方法就好了", 于是把init方法改寫(xiě)成了initWithFrame.以運(yùn)行,結(jié)果正確.

但是為什么重寫(xiě)init方法不行,重寫(xiě)initWithFrame方法就可以?

因?yàn)?init方法內(nèi)部會(huì)調(diào)用initWithFrame ,更準(zhǔn)確的說(shuō)法是:父類中的init方法會(huì)調(diào)用init方法內(nèi)部會(huì)調(diào)用initWithFrame方法.

這回又有點(diǎn)不明白了,方法是一層一層往上(父類)調(diào)用(本類中找不到,往父類中找,父類中找不到,往爺爺類中找...),你去調(diào)用父類的init方法,怎么就最終掉到了本類中的initWithFrame方法了?

有人說(shuō)這是因?yàn)镺C中的動(dòng)態(tài)特性,就是說(shuō)"在運(yùn)行時(shí)才去判斷對(duì)象的真實(shí)類型". 也就是說(shuō),你去調(diào)用父類的init方法,結(jié)果在父類中發(fā)現(xiàn)這個(gè)對(duì)象是子類(本類)的對(duì)象,于是找方法就跑到了子類的方法列表中去找了,于是就調(diào)用了子類(本類)的的方法了.

自定義控件的部分代碼:

@interface XMGShopView ()
@property (nonatomic ,weak)UIImageView *iconImageView;
@property (nonatomic ,weak)UILabel *namelabel;
@end

@implementation XMGShopView

/*
//重寫(xiě)init方法
- (instancetype)init
{
    if (self = [super init]) {
        // 添加圖片
        UIImageView *iconImageView = [[UIImageView alloc] init];
        [self addSubview:iconImageView];
        self.iconImageView = iconImageView;

        // 添加文字
        UILabel *nameLabel = [[UILabel alloc] init];
        nameLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:nameLabel];
        self.namelabel = nameLabel;

    }
    return self;
}
*/

//將init改寫(xiě)成initWithFrame
// 添加子控件,做初始化的設(shè)置,init方法內(nèi)部會(huì)調(diào)用initWithFrame
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        // 添加圖片
        UIImageView *iconImageView = [[UIImageView alloc] init];
        [self addSubview:iconImageView];
        self.iconImageView = iconImageView;

        // 添加文字
        UILabel *nameLabel = [[UILabel alloc] init];
        nameLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:nameLabel];
        self.namelabel = nameLabel;

    }
    return self;
}

- (instancetype)initWithShop:(XMGShop *)shop {
    if (self = [super init]) {
        self.shop = shop;
    }
    return self;
}

+ (instancetype)shopViewWithShop:(XMGShop *)shop {
    return [[self alloc] initWithShop:shop];
}
/**
 *  布局子控件,設(shè)置子控件的frame
 */
- (void)layoutSubviews
{
    // 這里一定要調(diào)用super
    [super layoutSubviews];

    CGFloat shopW = self.frame.size.width;
    CGFloat shopH = self.frame.size.height;

    self.iconImageView.frame = CGRectMake(0, 0, shopW, shopW);
    self.namelabel.frame = CGRectMake(0, shopW, shopW, shopH - shopW);

}
/**
 *  設(shè)置數(shù)據(jù)
 */
- (void)setShop:(XMGShop *)shop
{
    _shop = shop;
    self.iconImageView.image = [UIImage imageNamed:shop.icon];
    self.namelabel.text = shop.name;
}

1.3 父類調(diào)用子類方法

但這跟self 和 super 有什么關(guān)系?

要想不論用什么方法創(chuàng)建對(duì)象,都會(huì)掉用本類的initWithFrame方法,這樣是怎么實(shí)現(xiàn)的呢?

想知道實(shí)現(xiàn)?可惜看不到源碼,要是能看到源碼還會(huì)有這么一大推的廢話么.

去實(shí)現(xiàn)這個(gè)功能就可能跟 self 和 super 有關(guān)系了.

下面是模擬實(shí)現(xiàn)的代碼,代碼中定義了一個(gè)Person ,一個(gè)GoodPerson,繼承與Person. (把initWithName當(dāng)做initWithFrame)

并且不論用什么方法創(chuàng)建GoodPerson對(duì)象,都將調(diào)用GoodPerson 類中的 initWithName 方法, 就像自定義控件中,不論你用什么方法創(chuàng)建控件,都將調(diào)用本類中的 initWithName 方法.

其實(shí)這是因?yàn)樵诟割?person)中調(diào)用了[self initWithName:nil], 而此時(shí)self的值打印出來(lái)是子類的類型(GoodPerson),所以才有從父類的方法調(diào)用子類的方法這樣的跳轉(zhuǎn).

所以才有這樣的兩句話:

  • 不管是 self 還是 super 其消息主體依然是 self ,也就是說(shuō) self 和 super 指向的 是同一個(gè)對(duì)象。只是 查找方法的位置 區(qū)別,一個(gè)從本類瓢省,一個(gè)從本類的超類。
  • 添加子控件,做初始化的設(shè)置寫(xiě)在initWithFrame中,init方法內(nèi)部會(huì)調(diào)用initWithFrame, 所以你只需要重寫(xiě)initWithFrame方法,不管使用什么方法創(chuàng)建控件,都一定會(huì)調(diào)用initWithFrame.

完整代碼:

  • Person.h
#import <Foundation/Foundation.h>

@interface Person : NSObject
-(instancetype)init;
-(instancetype)initWithName:(NSString *)name;
@end
  • Person.m
#import "Person.h"

@implementation Person
-(instancetype)init{
    if (self = [self initWithName:nil]) {
    //if (self = [super init]) {
        NSLog(@"Person --- init");

        NSLog(@"%@",self);
    }
    return self;
}
-(instancetype)initWithName:(NSString *)name{
    if (self = [super init]) {
        NSLog(@"Person --- initWithName");
      //  NSLog(@"%@",self);
    }
    return self;
}
@end
  • GoodPerson.h
#import "Person.h"

@interface GoodPerson : Person
@property(nonatomic,assign)int age;
-(instancetype)init;
-(instancetype)initWithName:(NSString *)name;

-(instancetype)initWithAge:(int)age;
+(instancetype)GoodPersonWithAge:(int)age;
@end
  • GoodPerson.m
#import "GoodPerson.h"

@implementation GoodPerson
-(instancetype)init{
    if (self = [super init]) {
        NSLog(@"GoodPerson --- init");
    }
    return self;
}
-(instancetype)initWithName:(NSString *)name{
    if (self = [super initWithName:name]) {
        NSLog(@"GoodPerson --- initWithName");
    }
    return self;
}

-(instancetype)initWithAge:(int)age{
    if (self = [super init]) {
        _age = age;
        NSLog(@"GoodPerson --- initWithAge");
    }
    return self;
}

+(instancetype)GoodPersonWithAge:(int)age{
    return [[GoodPerson alloc] initWithAge:age];
}
@end
  • main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "GoodPerson.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        GoodPerson *p = [GoodPerson GoodPersonWithAge:10];
        NSLog(@"age = %i",p.age);
    }
    return 0;
}
/*
輸出結(jié)果:
 Person --- initWithName
 GoodPerson --- initWithName
 Person --- init
 <GoodPerson: 0x100603a20>
 GoodPerson --- initWithAge
 age = 10
*/
/*
調(diào)用關(guān)系:
GoodPersonWithAge -> initWithAge (GoodPerson) ->
init(Person) -> initWithName(GoodPerson) ->
initWithName(Person) -> (NSObj 的init方法) ->  開(kāi)始返回.
*/

我也是剛接觸OC一個(gè)月,以上內(nèi)容都是瞎寫(xiě),被誤導(dǎo)了不要打我.
其實(shí)我也想知道真相

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末痊班,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子摹量,更是在濱河造成了極大的恐慌涤伐,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缨称,死亡現(xiàn)場(chǎng)離奇詭異凝果,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)睦尽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)器净,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人当凡,你說(shuō)我怎么就攤上這事山害。” “怎么了沿量?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵浪慌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我朴则,道長(zhǎng)权纤,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮汹想,結(jié)果婚禮上外邓,老公的妹妹穿的比我還像新娘。我一直安慰自己古掏,他們只是感情好坐榆,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著冗茸,像睡著了一般席镀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上夏漱,一...
    開(kāi)封第一講書(shū)人閱讀 50,096評(píng)論 1 291
  • 那天豪诲,我揣著相機(jī)與錄音,去河邊找鬼挂绰。 笑死屎篱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的葵蒂。 我是一名探鬼主播交播,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼践付!你這毒婦竟也來(lái)了秦士?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤永高,失蹤者是張志新(化名)和其女友劉穎隧土,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體命爬,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡曹傀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饲宛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片皆愉。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖艇抠,靈堂內(nèi)的尸體忽然破棺而出幕庐,到底是詐尸還是另有隱情,我是刑警寧澤练链,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布翔脱,位于F島的核電站,受9級(jí)特大地震影響媒鼓,放射性物質(zhì)發(fā)生泄漏届吁。R本人自食惡果不足惜错妖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望疚沐。 院中可真熱鬧暂氯,春花似錦、人聲如沸亮蛔。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)究流。三九已至辣吃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芬探,已是汗流浹背神得。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留偷仿,地道東北人哩簿。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像酝静,于是被迫代替她去往敵國(guó)和親节榜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • http://www.cocoachina.com/cms/wap.php?action=article&id=1...
    Kevin追夢(mèng)先生閱讀 1,014評(píng)論 0 3
  • 來(lái)源:騰訊大講堂 本文檔整理大部分公認(rèn)的别智、或者少有爭(zhēng)議的JavaScript良好書(shū)寫(xiě)規(guī)范(Best Practic...
    JustFantasy閱讀 399評(píng)論 0 0
  • 1截止日期是第一生產(chǎn)力 2成功與失敗宗苍,只是某一刻的狀態(tài),在它們之間亿遂,還有無(wú)數(shù)個(gè)過(guò)渡階段浓若,也就是我們所說(shuō)的成長(zhǎng)。不斷...
    恍然如誓閱讀 256評(píng)論 0 0
  • 曾經(jīng)蛇数,我是不相信有命運(yùn)這種東西的,小的時(shí)候認(rèn)為一切還不算太糟糕是越,一切都有機(jī)會(huì)改變耳舅,我的人生沒(méi)有任何禁錮,我能在度過(guò)...
    DashanzhaWan閱讀 230評(píng)論 0 0
  • 睡前好事冥想倚评,該給種子澆水施肥曬太陽(yáng)了浦徊,近期目標(biāo)是20170601以后每月收入一萬(wàn)塊,我自己增加三個(gè)代理商(合作伙...
    馬忠娟閱讀 126評(píng)論 0 1