ClassA.h
@interface classA
-(void)print1;
-(void)print2;
@end
ClassA.m
-(void)print1 {
NSLog(@"I am class A 1");
}
-(void)print2 {
NSLog(@"I am class A 2");
}
ClassB.h
@interface classB : classA
-(void)print1;
@end
ClassB.m
-(void)print1 {
NSLog(@"I am class B");
}
AppDelegate.m
ClassA *a1 = [[ClassB alloc]init];
[a1 print1];
[a1 print2];
输出
I am class B
I am class A 2
错误
ClassB *a1 = [[ClassA alloc]init];
问题
ClassB
是ClassA
的孩子,意味着ClassB
具有ClassA
功能,也有自己的ClassA
功能。但是ClassB
不知道classA *a1 = [[classB alloc]init];
是它的孩子。
那么classB *a1 = [[classA alloc]init];
如何工作并给出上述输出
而{{1}}正在给出错误
答案 0 :(得分:1)
对于classA *a1 = [[classB alloc]init];
的情况,因为在Objective-C中,方法在运行时被解析。 [a1 print1]
向a1
对象发送一条消息,该消息可以是运行时的任何内容,以调用方法print1
。即使你可以调用[a1 some_random_method]
编译器会发出警告而不是错误。因为,在运行时可能会添加some_random_method
。
对于第二个案例classB *a1 = [[classA alloc]init];
,我认为您会收到错误,因为并非所有classA
都是classB
。
classB
可能有额外的成员和方法。通过将classA
对象类型转换为classB
,您将尝试访问那些具有未定义行为的额外成员和方法。因此,编译器不支持从classA
到classB
的隐式类型转换,并且会出错。
但是,您可以明确地将classA
对象强制转换为classB
。在运行时,您可以向此对象添加classB
特有的方法(objective-C支持在运行时添加方法)并调用它们。
答案 1 :(得分:1)
[[classB alloc]init]
- 这是您实际创建对象的部分,而classA *a1
只是一个声明,简单地说,是什么将是"预期"从这个对象来看。您的classB是classA的子类,因此它具有classA所具有的所有内容,因此在访问属性或使用方法时不会导致错误。
另一方面,当您创建一个classA实例并将其强制转换为classB时:
classB *a1 = [[classA alloc]init]
编译器希望这个对象能够执行classB能够做的事情,并且因为classB是classA扩展,所以它可能会导致错误。