Polymorphism

The compiler, even in the world of static typing, is perfectly happy for you to supply a subclass instance where a superclass type is declared. To see this, let’s start with the first line of the previous example:

UIButton* b = [UIButton buttonWithType:UIButtonTypeRoundedRect];

UIButton is a subclass of UIControl, which is a subclass of UIView. So it would be perfectly legal and acceptable to say this:

UIButton* b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
UIView* v = b;

The variable b is a UIButton instance, but I’m assigning it to a variable declared as a UIView. That’s legal and acceptable because UIView is an ancestor (up the superclass chain) of UIButton. Putting it another way, I’m behaving as if a UIButton were a UIView, and the compiler accepts this because a UIButton is a UIView.

What’s important when the app runs, however, is not the declared class of a variable, but the actual class of the object to which that variable points. Even if I assign the UIButton instance b to a UIView variable v, the object to which the variable v points is still a UIButton. So I can send it messages appropriate to a UIButton. For example:

UIButton* b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
UIView* v = b;
[v setTitle:@"Howdy!" forState:UIControlStateNormal];

That code will cause the compiler to complain, because UIView doesn’t implement setTitle:forState:; under ARC, in fact, that code won’t even compile. So I’ll calm the compiler’s fears by typecasting:

UIButton* ...

Get Programming iOS 6, 3rd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.