所以我已经创建了一个我创建的UIViewController子类。问题是,有没有办法让我可以强制使用子类调用方法,如果我创建的是超类。我知道这是愚蠢的,因为它与强迫哺乳动物称呼狗的行为是一样的。但在此之前,我实际上确实确定那只哺乳动物是一只狗,否则我不会叫它。这是一件坏事吗?如果没有那么我该怎么做呢?我尝试将超类转换为它的子类,然后进行方法调用,但它不起作用。有什么想法吗?
所以我想做什么。我有一个UIViewController A和一个B的子类。如果我有A而我想调用B的方法来覆盖A,我该怎么做?我希望这很清楚
答案 0 :(得分:4)
您声明对象的方式与实际对象之间存在差异。 考虑这个例子:
Mammal *mammal = [[Dog alloc] init]; //Dog is a subclass of Mammal
在这里,您有一个指向Mammal
对象的指针,该对象实际指向专用Dog
类的实例。这是有效的,因为哺乳动物拥有狗的所有方法。
您可以使用Mammal
检查某个Dog
实例是否实际为isKindOfClass:
,如下所示:
if ([mammal isKindOfClass:[Dog class]]) {
[(Dog *)mammal bark];
}
这完全有效。但是,如果您使用mammal
创建了[[Mammal alloc] init]
,则Dog
类的检查将失败,您将无法调用仅Dog
具有的任何方法。如果你不做检查,这实际上会崩溃,因为转换不会以任何方式改变对象,它只是告诉编译器“我知道我在做什么,不要警告我”。
答案 1 :(得分:1)
我相信你只能走上层次结构,而不是失败。因此,基本上,您可以从类中调用超类,但不能调用子类。除非您通过将自身的引用传递给它的超类来初始化子类,否则它们之间没有任何关系。
这有点像你在找什么?
答案 2 :(得分:0)
我有一个UIViewController A和一个B的子类。如果我有A和 我想调用B的覆盖A的方法,我该怎么做?
您只需调用该方法即可。如果对象实际上是B的实例,那么将执行该方法的B版本。如果对象被实例化为A的实例,则将调用A的方法版本。亲自尝试一下,真正理解它:
@interface A : NSObject
{}
@end
@implementation A
- (void)whoAmI
{
NSLog(@"I'm an A\n);
}
@end
@interface B : A
@end
@implementation B
- (void)whoAmI
{
NSLog(@"I'm a B\n");
}
@end
//...
A *a = [[A alloc] init];
A *b = [[B alloc] init];
B *c = [[A alloc] init];
B *d = [[B alloc] init];
[a whoAmI]; // this will log "I'm an A"
[b whoAmI]; // this will log "I'm a B"
[c whoAmI]; // this will log "I'm an A"
[d whoAmI]; // this will log "I'm a B"
在子类的实现中,您可以使用super
关键字而不是self
来调用超类的方法。例如,B的另一种方法可以像这样调用B -whoAmI
:
[self whoAmI];
或者它可以像这样调用它的超类'实现:
[super whoAmI];
这在同一方法的覆盖中非常有用,因此您可以保留继承的行为,但可以添加它。 B -whoAmI
可以像这样实现:
- (void)whoAmI
{
NSLog(@"I'm a B\n");
[super whoAmI];
}
在这种情况下,上面的代码段会在评论中显示结果:
[a whoAmI]; // this will log "I'm an A"
[b whoAmI]; // this will log "I'm a B" followed by "I'm an A"
[c whoAmI]; // this will log "I'm an A"
[d whoAmI]; // this will log "I'm a B" followed by "I'm an A"
真正理解这些东西很重要,因为它是理解如何使用不同类型的对象的基础。所以花点时间写一些像这样的愚蠢的小样本程序,并继续提问,直到你确定你已经得到它为止。