Objective-C Posing

Posing,顧名思義,意思是“冒充”,它跟categories類似,但本質上不一樣,Posing存在的目的在於子類可以冒充父類,使得後續的代碼無需把父類修改為子類,就可以很方便的讓父類表現成子類的行為,從而實現非常方便的冒充,這在一般的語言中是難以想像的。

在開始在Objective-C中進行構建之前,提醒讀者注意,在Mac OS X 10.5中聲明已經棄用了冒充(Posing),並且之後無法使用它。 因此對於那些不關心這些棄用方法的人可以跳過本章。

Objective-C允許類完全替換程式中的另一個類。替換類被稱為“冒充”目標類。 對於支持冒充的版本,發送到目標類的所有消息都由冒充類接收。

NSObject包含poseAsClass - 使我們能夠替換現有類的方法,如上所述。

它允許擴展一個類,並且全面的冒充這個超類,比如:有一個擴展NSArrayNSArrayChild對象,如果讓NSArrayChild冒充NSArray,則程式代碼所在的NSArray都會自動替換為NSArrayChild
注意,這裏不是指代碼替換,而是NSArray所在地方的行為都跟NSArrayChild一樣了。

冒充限制

  • 一個類只能構成其直接或間接超類之一。
  • 冒充類不得定義目標類中不存在的任何新實例變數(儘管它可以定義或覆蓋方法)。
  • 目標類在冒充之前可能沒有收到任何消息。
  • 冒充類可以通過super調用重寫的方法,從而結合目標類的實現。
  • 冒充類可以覆蓋類別中定義的方法。

示例代碼:

#import <Foundation/Foundation.h>

@interface MyString : NSString

@end

@implementation MyString

- (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target
withString:(NSString *)replacement {
   NSLog(@"The Target string is %@",target);
   NSLog(@"The Replacement string is %@",replacement);
}

@end

int main() {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   [MyString poseAsClass:[NSString class]];
   NSString *string = @"Test";
   [string stringByReplacingOccurrencesOfString:@"a" withString:@"c"];

   [pool drain];
   return 0;
}

執行上面示例代碼,得到以下結果:

2018-11-22 21:23:44.729 Posing[372:306] The Target string is a
2018-11-22 21:23:44.730 Posing[372:306] The Replacement string is c

在上面的例子中,只是用實現污染了原始方法,並且這將通過上述方法在所有NSString操作中受到影響。


上一篇: Objective-C類別 下一篇: Objective-C擴展