This is a good and difficult question. Let's answer the three parts.
First part
To find the definition, it is important to realize that the name of the method is "Array", etc., which can be quite counterintuitive, since methods are usually lowercase...
irb> method(:Array)
=> #<Method: Object(Kernel)#Array>
This tells you these are defined in Kernel, and thus available everywhere without requiring an explicit prefix.
Second part
Array()
, String()
,... are conversion methods. Calling obj.to_a
will return an array, but will raise an NoMethodError
if obj doesn't respond_to? :to_a
. So the typical case when you'd prefer using Array()
, String()
, instead of to_a
or to_s
is when you are not positive an object responds to a given conversion method.
String(obj)
will return nil
if obj doesn't respond_to? :to_s
. String(obj) will also check that the result of to_s is actually a string; it should be, but maybe an overly creative programmer decided to return something else?
Most other conversion methods act the same way, but Array(obj)
is different. It will return [obj]
if obj doesn't respond_to? :to_a
. It will actually call to_ary
(which is the implicit conversion operation, while to_a
is the explicit one).
There is another important way to convert objects in 1.9 (and upcoming 1.8.8): Array.try_convert(obj)
. This returns nil
if the obj does not respond_to? :to_ary
. It will not call the to_a
. Although they are longer to type, you might prefer using them when writing very general code that might accept different types of objects and want to avoid converting a hash to an array by mistake, for example (since Hash
has a to_a
method but not to_ary
). When your method requires an array-like object and you are willing to do an explicit conversion, then obj.to_a
is fine. The typical use of Array(obj)
would be in a method that accepts either a single obj
to act on, or a list of objects (although typically this is written as [*obj]
).
Last part
Hopefully, the answers to the first two parts give you your final answer...
You can use:
[Integer, String, Array].each {|klass| klass.try_convert(foo) }
or
[:Integer, :String, :Array].each{|method| send(method, obj)}