OC 中一個類只有一個父類, 這就是單一繼承, 但是我們可以用協議和 NSProxy 實現多繼承
比如我有兩個協議, 分別是 YFPerson,YFChild
#import @protocol YFPerson @required @property (nonatomic,copy,readonly)NSString *name; - (NSInteger) age; - (void)eat; - (void)sleep; @optional - (void)play; - (void)setName:(NSString *)newName; @end
#import @protocol YFChild @required - (NSString *)nickname; - (void)introduceMyselfWithName:(NSString *)name nickname:(NSString *)nickname age:(NSInteger)age; @optional - (void)study; @end
那麼, 我在新創建的一個 YFStudent 類中, 只要遵守上面兩個協議, 實現協議裡的方法, 就可以在一個類中,實現多個協議中的方法了.
YFStudent.m
- (NSString *)nickname
{
return @"龍兒";
}
- (NSInteger)age
{
return 19;
}
- (void)sleep{
NSLog(@"sleep");
}
- (void)eat{
NSLog(@"eat");
}
- (void)introduceMyselfWithName:(NSString *)name nickname:(NSString *)nickname age:(NSInteger)age
{
NSLog(@"我叫%@,小名%@,今天%@歲了", name,nickname,@(age));
}這樣, 我在控制器的 viewDidLoad 方法中,創建 YFStudent 對象, 然後就可以調協議中的任何方法了
- (void)viewDidLoad {
[super viewDidLoad];
YFStudent *student = [[YFStudent alloc]init];
student.name = @"小龍女";
[student eat];
[student sleep];
[student introduceMyselfWithName:student.name nickname:student.nickname age:student.age];
}運行後,正確輸出

這個類是和 NSObject 平起平坐的, 而且這個類沒有 init 方法,也就是說,它只可以開辟一塊內存空間,而不能初始化. 那麼,我怎麼樣這個類可以變成任意一個類呢?
主要有這樣幾步,
我先設置一個類 YFProxy, 繼承自 NSProxy
為 YFProxy 設置一個 NSObject 屬性
自定義一個轉換方法,相當於給 NSObject 屬性賦值
然後通過這個屬性獲得調用方法的方法簽名
為調用設置目標
調用
我一步步說一遍
1.為外界暴露一個變身方法:
#import @interface YFProxy : NSProxy - (id)transformToObject:(NSObject *)object; @end
2.設置一個 NSObject 屬性
#import "YFProxy.h" @interface YFProxy () @property (nonatomic,strong)NSObject *object; @end
3.實現變身方法
- (id)transformToObject:(NSObject *)object
{
self.object = object;
return self.object;
}4.重寫- (NSMethodSignature *)methodSignatureForSelector:(SEL)see方法獲得方法簽名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
NSMethodSignature *methodSignature;
if (self.object) {
methodSignature = [self.object methodSignatureForSelector:sel];
}else{
methodSignature = [super methodSignatureForSelector:sel];
}
return methodSignature;
}5.重寫- (void)forwardInvocation:(NSInvocation *)invocation方法改變調用對象,也就是說,讓消息實際上發給真正的實現這個方法的類
- (void)forwardInvocation:(NSInvocation *)invocation
{
if (self.object) {
[invocation setTarget:self.object];
[invocation invoke];
}
}假設我現在有兩個類,
YFPerson
#import "YFPerson.h"
@interface YFPerson ()
@property (nonatomic,copy)NSString *name;
@end
@implementation YFPerson
- (void)eat
{
NSLog(@"%@正在吃飯",self.name);
}
@endYFStudent
#import "YFStudent.h"
@interface YFStudent ()
@property (nonatomic,copy)NSString *studentNum;
@end
@implementation YFStudent
- (void)study
{
NSLog(@"哥正在學習");
}
@end那麼我怎麼用 YFProxy"繼承"這連個類呢?
先初始化兩個純潔的對象
YFPerson *person = [[YFPerson alloc]init]; YFStudent *student = [[YFStudent alloc]init];
為 YFProxy 開辟一塊內存空間
YFProxy *proxy = [YFProxy alloc];
變身
[proxy transformToObject:person];
這樣就可以自由自在地調用 Person 類的方法了,person 類的方法甚至是真私有的,都可以調得到,雖然報警告了
[proxy performSelector:@selector(setName:) withObject:@"小明"]; [proxy performSelector:@selector(eat)];
再變
[proxy transformToObject:student];
這樣又可以調 Student類的方法了
[proxy performSelector:@selector(study)];
是不是很神奇,當然,這只是初步的探討,還有很多基於 OC 運行時的東西值得我們去挖掘