Subclasses and target casting C

Today I ran into some strange problem. I created a subclass of UIView and added only 1 method to the template code provided by 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:

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

Pretty simple, right? What does it print? I thought it would be something like "10.0000", but no, it prints "0.000000".

I struggled with this watch trying to figure out what I am doing wrong, and then I changed the code in the appDelegate app to

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

Only after that I printed the expected "10.0000". Why is this so? I declared FloatView as a subclass of UIView, should I not be able to assign a FloatView object to a UIView pointer without problems?

Despite the fact that the floatView was declared a pointer to a UIView, is it really a floatView and should be able to handle the floatTest message? Am I completely out of here?

+4
source share
1 answer

In fact, polymorphism works as expected. If this did not work, nothing would be printed (0.0000 is printed in your example). The fact is that your instance actually responds to the testFloat:10.0f , since the compiler cannot statically see the method declaration (since the UIView class UIView not declare such a method), it assumes that your method takes ... as an argument and returns id .

When CGFloat is passed to a method that expects a variable number of arguments ( ... ), it advances to double . Thus, the receive method is passed with the double argument and considers it a float , and it does not print correctly.

You can check this behavior by changing the NSLog line to:

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

When the compiler sends the message FloatView* , not UIView* , it can find the exact signature of the method. He can see that he really expects CGFloat and does not support the double argument. As a result, it works correctly.

Also, if UIView* contains the method declaration that CGFloat took, the compiler would CGFloat this method accordingly. To summarize, this is not a polymorphism problem; this is a missing signature issue.

+11
source

All Articles