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:. So I’ll calm the compiler’s fears by typecasting:

UIButton* b = [UIButton buttonWithType:UIButtonTypeRoundedRect]; ...

Get Programming iOS 4 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.