「Objective-C」類和方法

1. 類方法和對象方法

對象方法

  • 減號 - 開頭
  • 只能由對象來調(diào)用
  • 對象方法中能訪問當(dāng)前對象的成員變量(實例變量)

類方法

  • 加號 + 開頭
  • 只能由類(名)來調(diào)用
  • 類方法中不能訪問成員變量(實例變量)

類方法的好處和使用場合

  • 不依賴于對象,執(zhí)行效率高
  • 能用類方法,盡量用類方法
  • 場合:當(dāng)方法內(nèi)部不需要使用到成員變量時,就可以改為類方法

可以允許類方法和對象方法同名

2. self 關(guān)鍵字

self 的用途

  • 誰調(diào)用了當(dāng)前方法,self就代表誰
  • self出現(xiàn)在 對象/類 方法中,self就代表 對象/類
  • 成員變量和局部變量重名

當(dāng)成員變量和局部變量同名時,采取就近原則,訪問的是局部變量
用self訪問成員變量,區(qū)分同名的局部變量

使用細(xì)節(jié)

  • 出現(xiàn)的地方:所有的OC方法中(對象方法\類方法),不能出現(xiàn)在函數(shù)
  • 作用
    使用 "self->成員變量名" 訪問當(dāng)前 對象\類 方法調(diào)用的成員變量
    使用 "[self 方法名];" 來調(diào)用方法(對象方法\類方法)

3. 繼承

好處:

  • 抽取重復(fù)代碼
  • 建立類之間的關(guān)系
  • 子類可以擁有父類中 所有的 成員變量 和 方法

壞處:增強了代碼的耦合性
重寫:子類 重新實現(xiàn) 父類的某個方法,覆蓋父類以前的方法

使用情境:

  • A是B,則A繼承B
  • A擁有B,則A組合B「即B為A內(nèi)部的一個成員變量」

super 關(guān)鍵字

  • 直接調(diào)用父類的 成員變量 和 對象方法
  • 使用情景:子類重寫父類方法時想保留父類的一些行為

注意

  • Objective-C 是 單繼承
  • 基本上所有類的根類是NSObject
  • 不允許子類和父類擁有相同名稱的成員變量
  • 父類必須聲明在子類前面「實現(xiàn)不用在子類前」
  • 調(diào)用某個對象/類的方法時,優(yōu)先去當(dāng)前 對象/類 中找,若找不到去父類中找
  • 子類會繼承父類所有的變量「不管是否是私有,只是能不能直接訪問的問題」
  • 父類只在 implementation 里定義的變量,子類也會繼承

4. 多態(tài)「多種形態(tài)」

定義:父類指針 指向 子類對象
作用:若參數(shù)中使用的父類類型,則可以傳入父類、子類對象
注意

  • 編譯時 編譯器會檢查當(dāng)前類型對應(yīng)的類中有沒有調(diào)用方法「因為OC是弱語法」
  • 運行時 系統(tǒng)會動態(tài)檢測對象的真實類型
  • 局限性:父類型變量不能直接調(diào)用子類的方法「可以通過強制轉(zhuǎn)換來實現(xiàn)」

5. 對象和對象的關(guān)系

組合關(guān)系:類型相同 或 實現(xiàn)同一接口 的對象組合到一起
依賴關(guān)系:A對象 做 B對象的 形參 或 方法的局部變量,B 依賴 A
關(guān)聯(lián)關(guān)系:A對象 做 B對象的 一個成員變量,A 和 B 有關(guān)聯(lián)關(guān)系

6. 構(gòu)造方法

完整的創(chuàng)建一個對象「new 方法的步驟」

  1. 調(diào)用 +alloc 方法,分配存儲空間,返回一個對象 Cat *c = [Cat alloc];
  2. 調(diào)用 -init 方法,進(jìn)行初始化,把成員變量的值初始化為 0,返回初始化的原來對象 c = [c init];
    [Cat new] == [[Cat alloc] init]

目的:對象創(chuàng)建出來,成員變量就有一些固定的值
方法:

  • 重寫 - init 方法
// implementation 中
- (instancetype)init {
    // 1.調(diào)用 父類「super」 的 init 方法:初始化父類中聲明的 成員變量屬性 和 其他屬性
    self = [super init]; // 得到當(dāng)前對象 self
    if (self != nil) { // 初始化成功,nil 是空 == 0
        _min = 10; // 2. 進(jìn)行子類內(nèi)部成員的初始化
    }
    return self;// 返回已經(jīng)初始化完畢的對象
}
  • 自定義構(gòu)造方法
// implementation 中
- (instancetype)initWithAge : (int)age {
    // 簡化寫法

    if (self = [super init]) { 
        _age = age;
    }
    return self;
}

7. 類的聲明可以不寫「僅僅警告」

  • 有類的聲明
// 聲明
@interface Sample : NSObject {
    // 可以有成員變量
    int a; // 默認(rèn)@protected}

- (void)test;
@end

// 實現(xiàn)
@implementation Sample {
    // 也可以有成員變量「這種做法很少見」
    int b; // 默認(rèn) @private
    //注意:interface 和 implementation 不能聲明同名的成員變量
}

- (void)test{
    NSLog(@"有類的聲明");
}
@end
  • 沒有類的聲明「實現(xiàn) 必須寫在main函數(shù)之前」
// 實現(xiàn)
@implementation Sample : NSObject
- (void)test{
    NSLog(@"沒有類的聲明");
}
@end

8. id 和 instancetype 數(shù)據(jù)類型

實質(zhì):id 和 instancetype 都是 萬能指針類型,能 指向/操作 任何 objc 對象
區(qū)別:

  • id 在編譯時,不能 判斷對象的真實類型
    可以 定義變量,作為返回值,作為形參
  • id 不能用點語法,id可以調(diào)用任何對象的方法「這樣不利于編譯器檢查錯誤」
  • instancetype 編譯時,判斷對象的真實類型
    只能用于返回值

注意:自定義構(gòu)造方法 返回值 盡量使用 instancetype 而不是 id
用法:

id  d = [Person new]; // d為指針,id 類似于 NSObject *
NSObject *o =  [Person new];

9. @class 關(guān)鍵字

  • 格式:@class 類名1, 類名2 「注:為了可讀性,一般一個@class 對應(yīng)一個類名」
  • 僅僅告訴編譯器 類名 是個類,防止兩個類互相調(diào)用.h文件 編譯器報錯
  • 開發(fā)中引用的 類規(guī)范:
    1. 在 .h 文件中用 @class 來聲明
    2. 在 .m 文件中用 #import 來包含類所有的東西
  • @class 優(yōu)點:
    多個頭文件 #import 了同一個頭文件 a時,若 a 稍有改動,則這多個頭文件就都要重新編譯,為了減輕編譯器的負(fù)擔(dān) 使用 @class

10. 類的本質(zhì)

類對象:類本身也是個對象,是 Class 類型對象
Class 類型定義:<code>typedef struct objc_class *Class;</code>
為了調(diào)用類方法,獲取類對象「對象的類」:<code>Class n = [對象名 class];</code> 或 <code>Class n = [類名 class];</code>

11. 分類 Category

作用:在不改變原來類內(nèi)容的基礎(chǔ)上,為類添加方法「繼承也有這樣的作用」
好處:一個龐大的類可以分模塊開發(fā),由多人編寫,更有利于團隊合作
用法:分類可以定義在 單獨的 .m文件和 .h文件中,也可以定義在原來類中

  • 一般情況下,都定義在單獨文件中
  • 定義在原來類中的分類,只要能看懂語法就好

格式:

  • 在 原類名+分類名.h 文件中「文件名是規(guī)范」
#import "原類名.h"
@interface 類名 (分類名)
    // 方法聲明;
@end
  • 在 原類名+分類名.m 文件中
#import "原類名+分類名.h"
@implementation 類名 (分類名)
    // 方法實現(xiàn)
@end;

注意:

  • 分類只能增加 方法,不能增加 成員變量
  • 分類方法可以訪問原來類的成員變量
  • 分類可以覆蓋原來類同名的方法,會使類中原來的方法失效
  • 方法調(diào)用優(yōu)先級:1.分類「最后參與編譯的分類優(yōu)先」→ 2.原來類 → 3.父類

12. Class Extension 類擴展

定義:匿名的 Category,寫在 .m/.h 文件中
作用:為某個類擴充一些私有的 成員變量 和 方法 的聲明
格式:

#import "A.h" // 在 .m 文件中
// 類擴展
@interface A(){
    int _a; // 私有的成員變量 _a
}
- (void)sum(int) :a addWith :(int)b; // 是聲明
@end

@implementation A {
    int _b;
}
- (void)function{
    // 實現(xiàn)
}
@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容