比方说ClassA
,ClassB
和ClassC
定义如下:
@interface ClassA : NSObject {
}
- (void)methodA;
@end
@interface ClassB : ClassA {
}
- (void)methodB;
@end
@protocol ClassCProtocol <NSObject>
- (void)protocolMethodC;
@end
@interface ClassC : ClassA <ClassCProtocol> {
}
@end
为了使事情变得有趣,我还定义了一个@protocol
名为ClassCProtocol
从<NSObject>
协议继承,以及一个ClassC
对象是ClassA
的一个子类,并符合<ClassCProtocol>
协议(所有真正意思是符合协议的任何对象都保证实现-protocolMethodC
方法)。
首先要注意的是,在Objective-C中,与C++中的派生类没有同样的意义:只有单一继承,所以我们通常谈论的是ClassB
ClassA
的子类或ClassC
是ClassA
的子类。
然后采取下面的代码,假设MDLoadObject()
是将返回基于力所能及的情况下的ClassA
,ClassB
,或ClassC
实例的功能:
ClassA *MDLoadObject() {
ClassA *object = nil;
if (...) {
object = [[[ClassA alloc] init] autorelease];
} else if (...) {
object = [[[ClassB alloc] init] autorelease];
} else {
object = [[[ClassC alloc] init] autorelease];
}
return object;
}
@interface MDAppController : NSObject {
}
- (void)loadObject:(id)sender;
@end
@implementation MDAppController
- (void)loadObject:(id)sender {
ClassA *instanceOfClassABorC = MDLoadObject();
if ([instanceOfClassABorC isKindOfClass:[ClassB class]]) {
[(ClassB *)instanceOfClassABorC methodB];
} else if ([instanceOfClassABorC isKindOfClass:[ClassC class]]) {
[(ClassC *)instanceOfClassABorC protocolMethodC];
} else if ([instanceOfClassABorC respondsToSelector:@selector(protocolMethodC)) {
[(ClassC *)instanceOfClassABorC protocolMethodC];
} else {
}
}
@end
由于类ClassB
和ClassC
最高的共同祖先ClassA
,我们定义MDLoadObject()
函数返回ClassA
的实例。 (请记住,在单一继承中,ClassB
和ClassC
的所有实例也保证为ClassA
的实例)。
然后,-loadObject:
方法显示了Objective-C的活力,并且您可以通过几种方法查询此时MDLoadObject()
函数返回的对象类型。需要注意的是-loadObject:
方法也没有石膏被写入,它会在运行时运行得很好:
- (void)loadObject:(id)sender {
ClassA *instanceOfClassABorC = MDLoadObject();
if ([instanceOfClassABorC isKindOfClass:[ClassB class]]) {
[instanceOfClassABorC methodB];
} else if ([instanceOfClassABorC isKindOfClass:[ClassC class]]) {
[instanceOfClassABorC protocolMethodC];
} else if ([instanceOfClassABorC respondsToSelector:@selector(protocolMethodC)) {
[instanceOfClassABorC protocolMethodC];
} else {
}
}
这似乎可以工作。我唯一担心的是,由于我没有编写ClassB,它的结构可能会在以后的版本中发生变化,于是我不得不重新编写这个类。虽然我不认为这是一个问题,但我很好奇它是否有办法解决问题。 – Paul 2011-05-29 20:57:16
@Paul:“我只关心它,因为我没有写'ClassB' ...”。在你的问题中,你陈述了“'我想创建一个派生类,比如ClassB'”,这听起来好像你**完全控制它。也许你可以编辑你的问题,使其更清楚? – NSGod 2011-05-30 00:05:25