假設(shè)C類要同時(shí)繼承A類和B類,則稱之為多繼承补箍。而Objective-C不支持多繼承卒蘸,由于消息機(jī)制名字查找發(fā)生在運(yùn)行時(shí)而非編譯時(shí)校辩,很難解決多個(gè)基類可能導(dǎo)致的二義性問(wèn)題。不過(guò)其實(shí) Objective-C 也無(wú)需支持多繼承哥纫,我們可以找到如下幾種間接實(shí)現(xiàn)多繼承目的的方法:
通過(guò)組合實(shí)現(xiàn)“多繼承”
通過(guò)協(xié)議實(shí)現(xiàn)“多繼承”
通過(guò)category實(shí)現(xiàn)“單繼承”(大部分網(wǎng)上文章將此方法誤解成“多繼承”)
通過(guò)這幾種方法實(shí)現(xiàn)的“多繼承”霉旗,與真實(shí)的多繼承還是有明顯的區(qū)別的,因此這里給所有的多繼承加上雙引號(hào)蛀骇。
通過(guò)組合實(shí)現(xiàn)“多繼承”
//定義ClassA以及其methodA
@interface ClassA : NSObject {
}
-(void)methodA;
@end
//定義ClassB以及其methodB
@interface ClassB : NSObject {
}
-(void)methodB;
@end
//定義ClassC以及其需要的methodA厌秒,methodB
@interface ClassC : NSObject {
ClassA *a;
ClassB *b;
}
-(id)init;
-(void)methodA;
-(void)methodB;
@end
//注意在ClassC的實(shí)現(xiàn)
@implementation ClassC
-(id)init{
a=[[ClassA alloc] init];
b=[[ClassB alloc] init];
}
-(void)methodA{
[a methodA];
}
-(void)methodB{
[b methodB];
}
通過(guò)協(xié)議實(shí)現(xiàn)“多繼承”
雖然OC在語(yǔ)法上禁止類使用多繼承,但是卻可以用協(xié)議來(lái)實(shí)現(xiàn)多繼承擅憔。協(xié)議只能提供接口鸵闪,而沒(méi)有提供實(shí)現(xiàn)方式,如果只是想多繼承基類的接口暑诸,那么遵守多協(xié)議無(wú)疑是最好的方法蚌讼。
此方法缺點(diǎn)比較明顯:需要修改兩個(gè)父類,同時(shí)并不能調(diào)用兩個(gè)父類的原生方法个榕,需要在子類中實(shí)現(xiàn)方法篡石。
1、定義ClassA 以及 ClassAProtocol
@interface ClassA : NSObject
@end
@protocol ClassAProtocol <NSObject>
-(void)a;
@end
2西采、定義ClassB 以及 ClassBProtocol
@interface ClassB : NSObject
@end
@protocol ClassBProtocol <NSObject>
-(void)b;
@end
3凰萨、定義ClassC
@interface ClassC : NSObject
-(void)c;
@end
//ClassC定義以及實(shí)現(xiàn)
#import <Foundation/Foundation.h>
#import "ClassC.h"
#import "ClassA.h"
#import "ClassB.h"
@interface ClassC:NSObject< ClassAProtocol, ClassBProtocol>
-(void)c;
@end
#import "ClassC.h"
@implement ClassC
-(void)a
{
}
-(void)b
{
}
-(void)c
{
}
@end
通過(guò)類別實(shí)現(xiàn)“單繼承”
首先摘錄一段網(wǎng)上對(duì)類的描述:
? 使用類別就是為了能夠?yàn)楝F(xiàn)有類添加新的方法,不用繼承該現(xiàn)有類,就可使用現(xiàn)有類的對(duì)象調(diào)用添加的方法了胖眷。
? 類別可以使類的實(shí)現(xiàn)分散在多個(gè)文件中.
? 類別中不能有變量武通,類別中沒(méi)有放變量的位置.
? 如果類中的方法和類別中的方法名稱相同,這將造成沖突珊搀,類別的方法將完全取代類的方法冶忱。
? 同一個(gè)類的不同類別聲明了相同的方法,這將導(dǎo)致不穩(wěn)定境析,哪個(gè)方法會(huì)被調(diào)用是不確定的.
網(wǎng)上很多介紹這種方法的文章囚枪,都給出了一個(gè)通過(guò)類別實(shí)現(xiàn)“單繼承”的例子,而非“多繼承”的例子簿晓,但卻得出實(shí)現(xiàn)了“多繼承”的結(jié)論眶拉,往往使初學(xué)者一知半解云里霧里。通過(guò)類別可以簡(jiǎn)單實(shí)現(xiàn)類似“單繼承”功能憔儿,要實(shí)現(xiàn)“多繼承”則相對(duì)復(fù)雜一些忆植,可以通過(guò)一個(gè)新類包含多個(gè)類別的方法來(lái)實(shí)現(xiàn)“多繼承”,并不推薦使用谒臼。這里也僅給出一個(gè)通過(guò)類別實(shí)現(xiàn)“單繼承”的例子朝刊,同時(shí)在繼承的“子類”中增加了兩個(gè)函數(shù)。
// 為上例中的A類增加一個(gè)方法(類似繼承)
// A+C.h
#import "A.h"
@interface A (C) //類別的聲明
- (void)setAddr:(NSString *)addr;
- (NSString *)addr;
@end
//
// A+C.m
//
#import "A+C.h"
#import <objc/runtime.h>
const char *Addr = "NSString *";
@implementation A (C) //注意此處類別的格式
- (void)setAddr:(NSString *)addr
{
objc_setAssociatedObject(self, Addr, addr, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)addr
{
NSString *addr = objc_getAssociatedObject(self, Addr);
return addr;
}
@end