From: "Mark Wilden" <mark / mwilden.com>

> Hmmm. Is it that objects change their type, or is it that variables do?

I don't see variables in ruby as having any type at all.  They merely
hold a reference to some object (any object.)

On a related note:

> If you think about it, the class of an object  
> is _continually_ being interrogated at runtime, in order to dispatch a  
> given message to the right method.

Ruby is more dynamic than that.

>> class Widget
>>   def initialize(x)
>>     puts "i'm turning #{x.inspect} into a widget!"
>>   end
>> end
=> nil
>> x = "ordinary"
=> "ordinary"
>> y = "fancy"
=> "fancy"
>> def y.to_widget
>>   Widget.new(self)
>> end
=> nil
>> x.respond_to? :to_widget
=> false
>> y.respond_to? :to_widget
=> true
>> y.to_widget
i'm turning "fancy" into a widget!
=> #<Widget:0x2c978b8>
>> x
=> "ordinary"


In my view, neither the variable 'x' nor 'y' changed in the
above example.  The object referenced by 'y' definitely 
changed.  If an object's type is defined by what methods
it responds to, then the type of the object referenced by
'y' changed.  But its class hierarchy did NOT change:

>> y.class
=> String
>> x.class
=> String
>> y.class.ancestors
=> [String, Enumerable, Comparable, Object, Kernel]
>> x.class.ancestors
=> [String, Enumerable, Comparable, Object, Kernel]


The only way to tell that the object referenced by 'y'
responded to :to_widget was to ask it.  However, in ruby,
even asking doesn't always prove anything:

>> z = "fancier"
=> "fancier"
>> def z.method_missing(id, *args)
>>   if id == :to_widget
>>     Widget.new(self)
>>   else
>>     super
>>   end
>> end
=> nil
>> z.respond_to? :to_widget
=> false
>> z.to_widget
i'm turning "fancier" into a widget!
=> #<Widget:0x2c95b18>


The use of method_missing is a perfectly valid programming
approach in ruby, used often to forward method calls on to
some delegate, or also used to manufacture previously
nonexisting methods on-the-fly.

An example of the latter is the Og (Object Graph) ORM 
library.[1]  One can invoke methods on a class representing
a database table, without said methods previously existing:

  class IPHost
    property :ip, String, :unique => true
    property :hostname, String
  end

  rec = IPHost.find_or_create_by_ip_and_hostname("1.2.3.4", "example.com")

Og is smart enough, using method_missing, to notice that
the method name begins with find_or_create_by_... and as
I recall it does a fairly simple split(/_and_/) on the
remainder of the method name to determine the column names
being referenced.

For optimization purposes, Og may also then define that
method dynamically, so that it will now exist to speed up
further invocations.  (But, semantically, of course, there's
no need for the method to literally be defined, as it could
continue to handle it via method_missing.)


One further small point of interest.  Notice that IPHost
doesn't inherit from anything.  (Except Object, by default.)

When the Og library is initialized, it reflects through
ObjectSpace looking for classes which have used its :property
method to define database columns.  And it includes an
appropriate module on such classes to imbue them with the
smarts they need to function.


All of the above being reasons why in Ruby, duck typing is
preferentially approached as "tell, don't ask."  

There is no infallible way to ask objects whether they 
respond to a particular method, so just Trust The Programmer
and call the method you expect to be there.  In the more 
rare cases (like the OP in this thread) where one finds a
need to ask, then ask the particular object if it responds
to the method in question.  Because querying its class
inheritance hierarchy, as we have seen above, is about the
least reliable and most overly restrictive approach.


[1] Og: http://oxywtf.de/tutorial/1.html


Regards,

Bill