我有两个班级
A.H
@interface A : UIView
@end
A.M
@implementation A
-(id)initWithCoder:(NSCoder*)aDecoder{
self = [super initWithCoder:aDecoder];
if(self){
[self initialize];
}
return self;
}
-(void)initialize{
[[NSNotificationCenter defaultCenter]addObserver:self name:keyboardnotificationwillshow];
}
@end
B.h
@interface B : A
@end
@implementation B
-(id)initWithCoder:(NSCoder*)aDecoder{
self = [super initWithCoder:aDecoder];
if(self){
[self initialize];
}
return self;
}
-(void)initialize{
//do some stuff to prepare B
[self setBackgroundColor:[UIColor redColor]];
}
@end
现在我把B放在界面构建器中并等待它通过故事板加载 但是!
现在问我的问题:
在以前用于编写代码的所有语言中,我上面写的实现会产生以下内容
现在我通过调试运行它,这是实际的结果: 创建B,initWithCoderB - > initWithCoderA - > initializeB - >返回B
我的实际问题是:为什么它会跳过initializeA?
记录输出
2014-05-19 14:45:23.270 MyApp[17780:60b] B initWithCoder
2014-05-19 14:45:23.270 MyApp[17780:60b] A initWithCoder
2014-05-19 14:45:23.272 MyApp[17780:60b] B initialize
2014-05-19 14:45:23.278 MyApp[17780:60b] B initialize
如果我将initializeA重命名为initStuffA,则这是日志输出
2014-05-19 14:48:41.700 MyApp[17795:60b] B initWithCoder
2014-05-19 14:48:41.701 MyApp[17795:60b] A initWithCoder
2014-05-19 14:48:41.701 MyApp[17795:60b] A initialize
2014-05-19 14:48:41.702 MyApp[17795:60b] B initialize
那么为什么我不能拥有2个与private同名的方法,而没有它们会相互重叠? 因为他们是私人的,我不能称他们为超级
答案 0 :(得分:3)
由于你重写了B类中的initialize方法,并且在调用initialize方法时创建了一个B类实例,它将指向继承层次结构中最深的实现(在你的例子中是B类的初始化方法) )
答案 1 :(得分:2)
你想在这里实现什么目标?
如果您希望接口B的实例通过接口A的initWithCoder
,则无需在接口B中覆盖它。只需将initialize
作为公共方法并调用:< / p>
- (void)initialize
{
[super initialize];
//Any further initialization here
}
目前,接口B并不知道它的超类也实现了一个名为initialize
的方法,因为它是一个私有方法。
如果接口A中的initWithCoder:
方法调用您的initialize
方法并且它是一个公共方法,那么当您创建接口B的实例时,它将通过initWithCoder:
接口A,然后到接口B的initialize
,然后应该调用[super initialize];
以确保执行接口A initialize
方法中的任何代码。
编辑1:
好的,所以接口B继承自接口A.
默认情况下(即使用空白实现),接口B的实例将与接口A完全相同,因为所有方法都将默认通过接口A中的实现。
作为界面A的孩子的界面B有机会覆盖界面A提供的公开的任何方法或属性。
要公开发布,请在.h
文件中声明。
如果你有一个方法,例如在接口A的updateView
文件中有.h
,那么接口B的实现就有机会覆盖它。如果您希望接口B在自身和接口A中执行操作,则需要使用super
关键字调用继承树。例如,在接口B(子代)的实现中具有以下内容:
- (void)updateView
{
[super updateView]; //This calls any code written in interface A's updateView method
//Add your own code here
}
这显示了您的子类执行继承,因为它可以访问由接口A创建的updateView
方法。
接口B,因为它是接口A的子接口,将使用其父类的实现填充任何空方法。在您的示例中,您在两个接口中都实现了initWithCoder:
。这是不必要的,并导致重写并发症。通过在接口B中省略initWithCoder:
的声明,它将使用接口A的实现,它的父类调用initialize
。每次重写方法实现并希望执行自己的代码和父类的代码时,您只需记住调用super。
希望这可以清除你在Objective-C中对继承的一些困惑。