Kao*_* Te 4 polymorphism objective-c
我今天遇到了一个奇怪的问题.我创建了一个UIView的子类,并且只为xcode提供的模板代码添加了一个方法.
@interface FloatView : UIView {
}
- (void)floatTest:(CGFloat)x;
@end
- (void)floatTest:(CGFloat)x {
NSLog(@"float was %f", x);
}
Run Code Online (Sandbox Code Playgroud)
然后在我的appDelegate中我有这样的代码:
UIView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];
Run Code Online (Sandbox Code Playgroud)
很简单吧?这打印出来的是什么?我认为它会像"10.0000",但不,它打印出"0.000000".
我花了几个小时挣扎,试图找出我做错了什么,然后我将appDelegate中的代码更改为
FloatView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];
Run Code Online (Sandbox Code Playgroud)
只有这样,它才打印出预期的"10.0000".为什么会这样?我已经将FloatView声明为UIView的子类,我不应该将一个FloatView对象分配给UIView指针而不会出现问题吗?
即使floatView被声明为UIView的指针,它实际上是一个floatView,它应该能够处理floatTest消息?我完全不在这里吗?
Meh*_*ari 11
实际上,多态性正在按预期工作.如果它不起作用,则不会打印任何内容(在您的示例中,正在打印0.0000).问题是,当你的实例实际响应testFloat:10.0f消息时,由于编译器不能静态地看到方法声明(因为UIView类没有声明这样的方法),它假定你的方法...作为参数并返回id.
当CGFloat传递给期望变量数量的参数(...)的方法时,它被提升为double.因此,接收方法传递double参数并认为它是a float并且它不能正确打印.
您可以通过将NSLog行更改为:来验证此行为:
NSLog(@"%f", *(double*)&x);
Run Code Online (Sandbox Code Playgroud)
当编译器将消息发送到FloatView*而不是a时UIView*,它可以找到该方法的确切签名.它可以看到它真的期望CGFloat并且不会促进论证double.结果,它正常工作.
另外,如果UIView*包含采用a的方法声明,CGFloat编译器将适当地调用该方法.总而言之,这不是多态性问题; 这是一个缺少方法签名问题.