我开始通过观看 YouTube 讲座来学习 Objective-C。在一次讲座中,老师说,每当你尝试调用一个对象的公共(public) API 中不存在的方法时,编译器都会警告你,但会让你这样做。另外,如果该方法确实存在,它将在运行时起作用。
举例说明:
我有两个类(class):车辆和船舶。 Vehicle 实现了移动方法,而 Ship 是 Vehicle 的子方法并实现了射击。
在讲座中,据说这段代码可以编译(带有警告):
Ship *s = [[Ship alloc] init];
Vehicle *v = s;
[v shoot];
事实上,这段代码是可以工作的。因为v实际上是一艘船。
但实际情况是编译器不允许我编译这段代码,因为在 Vehicle 公共(public) API 中不存在 shot。
编译器错误:“Vehicle”没有可见的@interface声明选择器射击
我真的很想知道老师是否错了或者我是否可以改变编译器的行为。有人可以帮助我吗?谢谢!
观察:我知道我可以使用 (id) 来做到这一点,我真的很想在这里了解有关 Objective-C 行为和语法的更多信息
类(class):
车辆.h:
@import Foundation;
@interface Vehicle : NSObject
- (void) move;
@end
车辆.m:
#import "Vehicle.h"
@implementation Vehicle
- (void) move {
NSLog(@"moving");
}
@end
ship.h:
#import "Vehicle.h"
@interface Ship : Vehicle
- (void) shoot;
@end
ship.m:
#import "Ship.h"
@implementation Ship
- (void) shoot {
NSLog(@"shooting");
}
@end
最佳答案
你的老师是对的,但他忘了提到一些重要的事情:他描述的语义是 pre-ARC 的。
几年前引入 ARC 后,编译器的类型检查变得更加重要,因为它需要知道确切的签名才能知道如何管理进出调用的数据。请参阅this question更详细地解释为什么会发生这种情况。
如果关闭 ARC,您会看到警告,但代码会编译。
关于Objective-C 编译器不允许我调用公共(public) API 中不存在的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28522251/