Ruby is an object-oriented programming language; this chapter will show you what that reallymeans. Like all modern languages, Rubysupports object-oriented notions like classes, inheiritance, and polymorphism. But Ruby goes further than other languages you may have used. Some languages are strict and some are permissive; Ruby is one of the most permissive languages around.Strict languages enforce strong typing, usually at compile type: a variable defined asan arrayc an’t be used as another data type. If a method takes an arrayas an argument,you can’t pass in an array-like object unless that object happens to be a subclassof the array class or can be converted into an array.
Ruby enforces dynamic typing, or duck typing (“if it quacks like a duck, it is aduck”). A strongly typed language enforces its typing everywhere, even when it’s not needed. Ruby enforces its duck typing relative to a particular task. If a variablequacks like a duck, it is one—assuming you wanted to hear it quack. When you want “swims like a duck” instead, duck typing will enforce the swimming, and notthe quacking.
Here’s an example. Consider the following three classes, Duck, Goose, and DuckRecording:
class Duck
def quack
'Quack!'
end
def swim
'Paddle paddle paddle...'
end
end class Goose def honk 'Honk!' end def swim 'Splash splash splash...' end end class DuckRecording def quack play end def play 'Quack!' end end
def make_it_quack(Duck duck)
duck.quack end make_it_quack(Duck.new) # => "Quack!" make_it_quack(DuckRecording.new) # TypeException: object not of type Duck def make_it_swim(Duck duck) duck.swim end make_it_swim(Duck.new) # => "Paddle paddle paddle..." make_it_swim(Goose.new) # TypeException: object not of type Goose swim: def make_it_quack(duck) duck.quack end make_it_quack(Duck.new) # => "Quack!" make_it_quack(DuckRecording.new) # => "Quack!" def make_it_swim(duck) duck.swim end make_it_swim(Duck.new) # => "Paddle paddle paddle..." make_it_swim(Goose.new) # => "Splash splash splash..."
Over time, strict languages develop workarounds for their strong typing (have you ever done a cast when retrieving something from an Java collection?), and then workarounds for the workarounds (have you ever created a parameterized Java collection using generics?). Rubyjust doesn’t bother with anyof it. If an object supports the method you’re trying to use, Ruby gets out of its way and lets it work. Ruby’s permissiveness is more a matter of attitude than a technical advancement. Python lets you reopen a class after its original definition and modify it after the fact, but the language syntax doesn’t make many allowances for it. It’s sort of a dirty little secret of the language.
In Ruby, this behavior is not only allowed, it’s encouraged. Some parts of the standard libraryadd functionalityto built-in classes when imported, just to make it easier for the programmer to write code. The Facets Core libraryadds dozens of convenience methods to Ruby’s standard classes. Ruby is proud of this capability, and urges programmers to exploit it if it makes their lives easier. Strict languages end up needing code generation tools that hide the restrictions and complexities of the language. Rubyhas code generation tools built right into the language, saving you work while leaving complete control in your hands (see Chapter 10). Is this chaotic? It can be. Does it matter? Only when it actually interferes with you getting work done. In this chapter and the next two, we’ll show you how to follow common conventions, and how to impose order on the chaos when you need it. With Rubyy ou can impose the right kind of order on your objects, tailored for your situation, not a one-size-fits all that makes you jump through hoops most of the time. These recipes are probably less relevant to the problems you’re trying to solve than the other ones in this book, but they’re not less important. This chapter and the next two provide a general-purpose toolbox for doing the dirtywork of actual programming, whatever your underlying purpose or algorithm. These are the chapters you should turn to when you find yourself stymied by the Ruby language itself, or grinding through tedious makework that Ruby’s labor-saving techniques can eliminate. Every other chapter in this book uses the ideas behind these recipes


Search
Categories


Print Article
Save as PDF
October 25, 2007, 9:47 pm
I enjoyed the tutorial. The last few paragraphs stated the case for Ruby's approach well IMHO.
A minor error might bother real beginners: "def make_it_quack(Duck duck)" is C/C++ style. As I'm sure you know, Ruby doesn't allow a "type" qualifier for its parameters.