Ruby aficionados swear by what they call "duck typing" and I figured, since I'd criticized C# in comparison with Ruby, it was only fair to return the favor.
You'll have noticed that in Ruby we don't declare the types of variables or methods--everything is just some kind of object. . . . If you've come to Ruby from a language such as C# or Java, where you're used to giving all your variables and methods a type, you may feel that Ruby is just too sloppy to use to write "real "applications. It isn't. . . . [O]nce you use Ruby for a while, you['ll] realize that dynamically typed variables actually add to your productivity in many ways. (p. 365)and
If you want to write your programs using the duck typing philosophy, you really only need to remember one thing: an object's type is determined by what it can do, not by its class. (p. 370) . . . You don't need to check the type of the arguments. If they support [the method you're calling], everything will just work. If they don't, your method will throw an exception anyway. . . . Now sometimes you may want more than this style of laissez-faire programming. ... (p. 371)and it goes on to explain that all you need to do is call respond_to? to see if an object responds to the method you're calling. And therein lies the problem. I have seen Ruby code littered with calls to respond_to? Rails calls it about 200 times. To use Dave Thomas' term, it's sloppy. Here's a typical use of respond_to?
def render(obj) case when obj.respond_to?(:to_html) return obj.to_html when obj.respond_to(:to_json) return json_to_html(obj.to_json) when obj.respond_to(:to_s) return html_encode(obj.to_s) else # Not realistic, since all objects respond to to_s raise "can't render" end endGee, wouldn't it be great if the language handled this automatically?
def render(IConvertsToHTML obj) return obj.to_html end def render(IConvertsToJSON arg) return json_to_html(obj.to_json) end def render(IConvertsToString arg) return html_encode(obj.to_s) endThe appropriate method can be decided dynamically at runtime — the decision is not made at compile time. But, once inside the methods, support for the specified interface could be guaranteed. Also, notice that there is no need for an extra method to handle the unrealistic error case that I tossed in to make this point, though we could certainly add any number of additional methods for additional things we want to convert.