简体   繁体   English

目标C中的子类化和强制转换

[英]Subclassing and Casting in Objective C

I came across a strange problem today. 我今天遇到了一个奇怪的问题。 I created a subclass of UIView and added only 1 method to the template code provided by xcode. 我创建了一个UIView的子类,并且只为xcode提供的模板代码添加了一个方法。

@interface FloatView : UIView {

}
- (void)floatTest:(CGFloat)x;
@end

- (void)floatTest:(CGFloat)x {
  NSLog(@"float was %f", x);
}

Then in my appDelegate I had code like this: 然后在我的appDelegate中我有这样的代码:

UIView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];

Pretty simple, right? 很简单吧? What should this print out? 这打印出来的是什么? I thought it would something like "10.0000", but no, it prints out "0.000000". 我认为它会像“10.0000”,但不,它打印出“0.000000”。

I wrestled with this for hours, trying to figure out what I was doing wrong, and then I changed the code in my appDelegate to 我花了几个小时挣扎,试图弄清楚我做错了什么,然后我将appDelegate中的代码更改为

FloatView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];

Only then, did it print out the expected "10.0000". 只有这样,它才打印出预期的“10.0000”。 Why is this so? 为什么会这样? I've declared FloatView as a subclass of UIView, shouldn't I be able to assign a FloatView object to a UIView pointer without problems? 我已经将FloatView声明为UIView的子类,我不应该将一个FloatView对象分配给UIView指针而不会出现问题吗?

Even though floatView was declared a pointer to a UIView, it's really a floatView and it should be able to handle the floatTest message? 即使floatView被声明为UIView的指针,它实际上是一个floatView,它应该能够处理floatTest消息? Am I totally off base here? 我完全不在这里吗?

Actually, polymorphism is working as expected. 实际上,多态性正在按预期工作。 If it didn't work, nothing would have been printed (in your example, 0.0000 is being printed). 如果它不起作用,则不会打印任何内容(在您的示例中,正在打印0.0000)。 The thing is, while your instance actually responds to testFloat:10.0f message, since the compiler can't statically see the method declaration (as UIView class doesn't declare such a method), it assumes that your method takes ... as argument and returns id . 问题是,虽然你的实例实际上响应了testFloat:10.0f消息,因为编译器不能静态地看到方法声明(因为UIView类没有声明这样的方法),它假定你的方法需要... as参数和返回id

When CGFloat is passed to a method that expects variable number of arguments ( ... ), it's promoted to double . CGFloat传递给一个需要可变数量的参数( ... )的方法时,它会被提升为double Thus, the receiving method is passed a double argument and thinks it's a float and it doesn't get printed correctly. 因此,接收方法传递一个double参数,并认为它是一个float ,它不能正确打印。

You can verify this behavior by changing NSLog line to: 您可以通过将NSLog行更改为:来验证此行为:

NSLog(@"%f", *(double*)&x);

When the compiler sends the message to FloatView* rather than a UIView* , it can find the exact signature of the method. 当编译器将消息发送到FloatView*而不是UIView* ,它可以找到该方法的确切签名。 It can see it really expects CGFloat and doesn't promote the argument to double . 它可以看到它真的期望CGFloat并且不会促使论证double As a result, it works correctly. 结果,它正常工作。

Additionally, if UIView* contained the method declaration that took a CGFloat , the compiler would call the method appropriately. 另外,如果UIView*包含采用CGFloat的方法声明,编译器将适当地调用该方法。 To summarize, this is not a polymorphism issue; 总而言之,这不是多态性问题; it's a missing method signature issue. 这是一个缺少方法签名问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM