Rubyists talk about methods calls as sending message to objects, a notion that I understand is inherited from Smalltalk. It always seemed a little strange, but I could accept it as an odd quirk (“Bah! I understand method calls!”) and move on to writing code. This is unusual behavior for me, since normally I try to understand a language on its own terms. Now, though, I think I finally grok all this talk of messages, thanks to A Little Ruby, A Lot of Objects, an incomplete book in the style of The Little Schemer. And as it turns out, terminology matters.
fido = Dog.new
speak method on fido (
fido.speak) is really sending a message to the
fido object. When
fido receives the “speak” message, it knows to invoke the
speak method. It answers, or returns, with the String “Woof!”
Yeah, that doesn’t seem too special, does it?
But here’s the thing. In Ruby, everything’s an object. 2 is an object of type Integer.
2 + 5 in Ruby is really saying, “Send the message “+” to the object
2, along with the parameter
5.” That is,
2 + 5 is convenient shorthand, syntactic sugar for
2.send("+",5) (which is, by the way, valid Ruby).
2 receives the message and invokes its
+ method, passing
5 as a parameter. It responds with 7.
Okay, this is still not seeming very special. Doesn’t this just muck up the discussion? Sure, it’s neat that 2 is an object, but what do you gain from all this talk of sending messages?
I’ll tell you where it finally clicked for me: polymorphism. I’m not sure why, but for some reason polymorphism is often a tricky concept for beginning programmers. Couched in terms of sending messages to objects, it’s crystal clear (at least to me :). You can send the same message to different objects, each of which will invoke the appropriate method of its class.
garfield = Cat.new
garfield.speak, we’re sending the message “speak” to the object.
fido receives the message and invokes its
speak method, and
garfield invokes its own
+ does different things for Strings and Integers. This is commonly called operator overloading.
2 + 5 == 7
"Abe " + "Lincoln" == "Abe Lincoln"
The message is the same: “+” — but the methods are different. Ah ha!
And now I finally understand duck typing in relation to polymorphism. It should have been obvious earlier, but I never thought of it in that way (probably because I figured that polymorphism wasn’t that tricky, so I didn’t think about it). Dave Thomas’s explanation of duck typing is fairly clear. In Ruby, types are defined by what objects can do rather than their class.
When I write
in Ruby, I don't care whether fred is a String, a File, or an Array
What matters instead is whether fred can respond to the message “A Little Ruby, A Lot of Objects, let me make it clear now: it is a fine read, highly recommended. And now I want to go read The Little Schemer.