To determine the class of an object in Ruby, simply ask for it:
o = "test" # This is a value o.class # Returns an object representing the String class
We can ask any class what its superclass is:
o.class # String: o is a String object o.class.superclass # Object: superclass of String is Object o.class.superclass.superclass # nil: Object has no superclass
In Ruby 1.9 and later, Object is no longer the root of the class hierarchy:
Object.superclass # BasicObject: Object has a superclass in 1.9 BasicObject.superclass # nil: BasicObject has no superclass
So a particularly straightforward way to check the class of an object is by direct comparison:
o.class == String # true if is o a String
The instance_of? method does the same thing and is a little more elegant:
o.instance_of? String # true if o is a String
Usually when we test the class of an object, we would also like to know if the object is an instance of any subclass of that class. To test this, use the is_a? method, or its synonym kind_of? :
x = 1 # This is the value we're working with x.instance_of? Fixnum # true: is an instance of Fixnum x.instance_of? Numeric # false: instance_of? doesn't check inheritance x.is_a? Fixnum # true: x is a Fixnum x.is_a? Integer # true: x is an Integer x.is_a? Numeric # true: x is a Numeric x.is_a? Comparable # true: works with mixin modules, too x.is_a? Object # true for any value of x
The Class class defines the === operator in such a way that it can
be used in place of is_a?
:
Numeric === x # true: x is_a Numeric
Every object has a well-defined class in Ruby, and that class never changes during the lifetime of the object.
Another way to put it is that the type of an object is the set of methods it can respond to
(This definition becomes recursive because it is not just the name of the methods that matter, but also the types of arguments that those methods can accept.)
In Ruby programming, we often don't care about the class of an object, we just want to know whether we can invoke some method on it.
<<
operator.
Arrays, strings, files, and other I/O-related classes define this as an append operator.
If we are writing a method that produces textual output, we might write it generically to use this operator.
<<
. We don't care about
the class of the argument, just that we can append to it. We can
test for this with the respond_to? method:
o.respond_to? :"<<" # true if o has an << operator
The shortcoming of this approach is that it only checks the name of a method, not the arguments for that method:
<<
as a left-shift operator and expect the
argument to be a number instead of a string.
There is no general solution
to this problem, but an ad-hoc remedy, in this case, is to explicitly
rule out Numeric objects with the is_a?
method:
o.respond_to? :"<<" and not o.is_a? Numeric
Another example of the type-versus-class distinction is the StringIO class (from Ruby's standard library).
is_a?
IO, then your method won't work with StringIO
arguments.
Focusing on types rather than classes leads to a programming style known in Ruby as "duck typing."
Repasa la sección Comprobación de Tipos y Tipado Pato (Duck Typing) 14.1.8.
El tipo de un objeto es el conjunto de conductas que caracterizan al objeto. Es el conjunto de métodos a los que puede responder.
Casiano Rodriguez León 2015-01-07