首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Objective-C 類擴展機制全解析:Category、Extension、Protocol 與 Delegate 模式

     編輯:關於C語言

Objective-C 類擴展機制全解析:Category、Extension、Protocol 與 Delegate 模式

Objective-C 通過 Category(分類)、Extension(類擴展)、Protocol(協議)三大機制實現類的功能擴展、私有接口管理與解耦通信。本文深度對比三者異同,並以經典「婚禮委託」示例完整演示 Protocol + Delegate 實戰模式。

一、Category(分類):為現有類動態添加方法

核心特點

  • 無需源碼、無需繼承,即可為任意類(包括系統類)添加實例方法/類方法。
  • 添加的方法成為原類一部分,子類可繼承,區別於繼承只能擴展子類。
  • 不能添加實例變量(ivar),但可通過關聯對象 objc_setAssociatedObject 實現類似效果。
  • 命名規範:ClassName+CategoryName.h/.m。

聲明與實現

// NSString+Reverse.h
@interface NSString (Reverse)
- (NSString *)reversedString;
@end

// NSString+Reverse.m
#import "NSString+Reverse.h"
@implementation NSString (Reverse)
- (NSString *)reversedString {
    NSMutableString *reversed = [NSMutableString stringWithCapacity:self.length];
    for (NSUInteger i = self.length; i > 0; i--) {
        [reversed appendFormat:@"%C", [self characterAtIndex:i-1]];
    }
    return reversed;
}
@end

// 使用
NSString *s = @"hello";
NSLog(@"%@", [s reversedString]); // "olleh"

Category vs Subclass 對比

維度CategorySubclass
添加方法✅✅
添加實例變量❌ (需關聯對象)✅
方法作用域原類及所有子類僅子類及其子類
調用方式原類實例/類直接調用需創建子類實例
適用場景系統類擴展、模塊化功能切片需存儲狀態、重寫父類行為

二、Extension(類擴展):私有接口的歸宿

核心特點

  • 只能用於擁有源碼的類,定義在 .m 文件頂部(類似私有頭文件)。
  • 用於聲明私有方法、私有屬性、協議遵循,隱藏實現細節。
  • 編譯器強制要求在 @implementation 中實現所有聲明的方法,否則警告。
  • 可添加實例變量(現代 Runtime 支持),@interface ClassName () { int _privateIvar; } @end。

語法示例

// MyClass.m
#import "MyClass.h"

@interface MyClass () // 無名分類 = Extension
@property (nonatomic, strong) NSString *privateCache; // 私有屬性
- (void)privateHelperMethod; // 私有方法
@end

@implementation MyClass
- (void)privateHelperMethod {
    // 實現細節對外不可見
}
@end

Category vs Extension

維度CategoryExtension
作用為無源碼類添加功能管理本類私有接口
文件結構獨立 .h/.m寫在 .m 文件內部
添加 ivar需關聯對象直接在大括號中聲明
編譯器檢查不強制實現強制在 @implementation 中實現

三、Protocol(協議)與 Delegate(委託)模式

協議本質

  • 定義一組方法簽名(僅聲明),類似 Java Interface / C++ 純虛類。
  • 方法默認 @required(必須實現),可用 @optional 標記可選方法。
  • 協議可繼承其他協議 @protocol MyProto 。

Delegate 六步走(以「結婚」為例)

  1. 聲明協議(女方定義標準):@protocol Marriage - (void)makeMoney; @optional - (void)cook; @end
  2. 設置代理屬性(女方持有代理):@property (nonatomic, weak) id delegate; 必須用 weak 避免循環引用。
  3. 觸發代理回調(女方通知):[self.delegate makeMoney];
  4. 遵循協議(男方簽署):@interface Groom : NSObject
  5. 指定代理(女方指定男方):bride.delegate = groom;
  6. 實現協議方法(男方履行):- (void)makeMoney { NSLog(@"我賺錢養家"); }

完整代碼示例

// Bride.h
@protocol Marriage 
@required - (void)makeMoney;
@optional - (void)cook; - (void)washClothes;
@end

@interface Bride : NSObject
@property (nonatomic, weak) id delegate;
@property (nonatomic, copy) NSString *name;
- (void)marry;
@end

// Bride.m
@implementation Bride
- (void)marry {
    NSLog(@"%@ 和 %@ 結婚了", self.name, self.delegate);
    [self.delegate makeMoney]; // 必須實現
    if ([self.delegate respondsToSelector:@selector(cook)]) {
        [self.delegate cook]; // 可選實現
    }
}
@end

// Groom.h
@interface Groom : NSObject 
@property (nonatomic, copy) NSString *name;
@end

// Groom.m
@implementation Groom
- (void)makeMoney { NSLog(@"%@ 負責掙錢", self.name); }
- (void)cook { NSLog(@"%@ 做飯", self.name); }
@end

// main.m
int main() {
    Bride *bride = [[Bride alloc] init]; bride.name = @"Mary";
    Groom *groom = [[Groom alloc] init]; groom.name = @"John";
    bride.delegate = groom; // 步驟5
    [bride marry]; // 觸發委託
    return 0;
}

Delegate 核心優勢

  • 解耦:Bride 不關心 Groom 具體類,只關心是否遵循 Marriage 協議。
  • 單向依賴:Bride 依賴協議,Groom 依賴協議,雙方不直接依賴彼此具體類。
  • 可替換性:可隨時換成 Bride 的其他代理(如律師、父母),無需修改 Bride 代碼。

總結

  • Category:橫向擴展現有類功能,無狀態擴展首選。
  • Extension:縱向封裝私有實現,.m 文件內部管理。
  • Protocol + Delegate:縱向解耦協作關係,代理屬性必須 weak,可選方法用 respondsToSelector: 保護調用。
  • 三者協同構建了 Objective-C 靈活、模塊化、可測試的架構基石。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved