**1.利用组合,把需要多继承的几个对象声明成自己的几个全局变量。然狗在相应的方法中直接调用即可。
**
2.通多遵守多个协议即可,但是自己还是得提供实现。原则上来说不能算是多继承。
3.可以考虑使用分类,他不会破坏元类的分装性,优先级更高,也是Apple比较推荐的一种方式。
4.消息转发机制
具体实例:
方法1. 组合方式,用ClassC 添加ClassA ,ClassB成员变量 来调用methodA,methodB
//定义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)initWithA:(ClassA *)A b:(ClassB *)B;-(void)methodA;-(void)methodB;@end//注意在ClassC的实现@implementation ClassC-(id)initWithA:(ClassA *)A b:(ClassB *)B{ a=[[ClassA alloc] initWithClassA: A];//[A copy];b=[[ClassB alloc] initWithClassB: B];//[B copy];}-(void)methodA{[a methodA];}-(void)methodB{[b methodB];}
方法2.协议protocol 设置ClassA delegate和 ClasssB delegate 以及实现方法ClassA里的methodA,和ClasssB里的methodB。ClassC遵守这两个协议就可以。【协议支持多继承】
方法3.类别(分类)
ClassC的类别 可以实现ClassA的methodA和ClassB的methodB两个方法,这样ClassC就可以调用methodA和methodB
方法4.消息转发机制
我们知道objective-c中调用方法的方式是发消息,那如果给一个实例对象发一个未定义的消息呢?结果就是crash,其实这中间系统给我们第二次机会,就是可以转发该消息
如果未调到定义的消息,runtime会给该实例第二次机会,首先调用methodSignatureForSelector 或去方法签名,然后调用forwardInvocation,如果用户自己定义的类,没有重写这两个方法,即不支持方法转发
-
@interface LOCBird : NSObject { NSString* name_; } @end @implementation LOCBird - (id)init { self = [super init]; if (self) { name_ = [[NSString alloc] initWithString:@"I am a Bird!!"]; } return self; } - (void)dealloc { [name_ release]; [super dealloc]; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSMethodSignature* signature = [super methodSignatureForSelector:aSelector]; if (signature==nil) { signature = [name_ methodSignatureForSelector:aSelector]; } NSUInteger argCount = [signature numberOfArguments]; for (NSInteger i=0 ; iNSLog(@"%s" , [signature getArgumentTypeAtIndex:i]); } NSLog(@"returnType:%s ,returnLen:%d" , [signature methodReturnType] , [signature methodReturnLength]); NSLog(@"signature:%@" , signature); return signature; } - (void)forwardInvocation:(NSInvocation *)anInvocation { NSLog(@"forwardInvocation:%@" , anInvocation); SEL seletor = [anInvocation selector]; if ([name_ respondsToSelector:seletor]) { [anInvocation invokeWithTarget:name_]; } } @end