In particular, an object can be operated on by only those methods that were defined for it. It can’t confuse
them with methods defined for other kinds of object, even if another object has a method with the same
name. This means that two objects can respond differently to the same message. For example, each kind of
object sent a display message could display itself in a unique way. A Circle and a Rectangle would respond
differently to identical instructions to track the cursor.
This feature, referred to as polymorphism, plays a significant role in the design of object-oriented programs.
Together with dynamic binding, it permits you to write code that might apply to any number of different
kinds of objects, without you having to choose at the time you write the code what kinds of objects they
might be. They might even be objects that will be developed later, by other programmers working on other
projects. If you write code that sends a display message to an id variable, any object that has a display
method is a potential receiver.
Dynamic Binding
A crucial difference between function calls and messages is that a function and its arguments are joined
together in the compiled code, but a message and a receiving object aren’t united until the program is
running and the message is sent. Therefore, the exact method that’s invoked to respond to a message can
only be determined at runtime, not when the code is compiled.
The precise method that a message invokes depends on the receiver. Different receivers may have different
method implementations for the same method name (polymorphism). For the compiler to find the right
method implementation for a message, it would have to know what kind of object the receiver is—what
class it belongs to. This is information the receiver is able to reveal at runtime when it receives a message
(dynamic typing), but it’s not available from the type declarations found in source code.
The selection of a method implementation happens at runtime. When a message is sent, a runtime messaging
routine looks at the receiver and at the method named in the message. It locates the receiver’s implementation
of a method matching the name, “calls” the method, and passes it a pointer to the receiver’s instance variables.
(For more on this routine, see Messaging in the Objective-C Runtime Programming Guide.)
This dynamic binding of methods to messages works hand-in-hand with polymorphism to give object-oriented
programming much of its flexibility and power. Since each object can have its own version of a method, a
program can achieve a variety of results, not by varying the message itself, but by varying just the object
that receives the message. This can be done as the program runs; receivers can be decided “on the fly” and
can be made dependent on external factors such as user actions.
When executing code based upon the Application Kit, for example, users determine which objects receive
messages from menu commands like Cut, Copy, and Paste. The message goes to whatever object controls
the current selection. An object that displays text would react to a copy message differently from an object
that displays scanned images. An object that represents a set of shapes would respond differently from a
Rectangle. Since messages don’t select methods (methods aren’t bound to messages) until runtime, these
differences are isolated in the methods that respond to the message. The code that sends the message
doesn’t have to be concerned with them; it doesn’t even have to enumerate the possibilities. Each application
can invent its own objects that respond in their own way to copy messages.
Objective-C takes dynamic binding one step further and allows even the message that’s sent (the method
selector) to be a variable that’s determined at runtime. This is discussed in the section Messaging in the
Objective-C Runtime Programming Guide.
Object Messaging 19
2009-10-19 | © 2009 Apple Inc. All Rights Reserved.
CHAPTER 1
Objects, Classes, and Messaging