Допустим, 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
method).
Первое, на что следует обратить внимание, это то, что в 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 {
}
}