Determining Type of an Object in Ruby

Determining type of an object in ruby

The proper way to determine the "type" of an object, which is a wobbly term in the Ruby world, is to call object.class.

Since classes can inherit from other classes, if you want to determine if an object is "of a particular type" you might call object.is_a?(ClassName) to see if object is of type ClassName or derived from it.

Normally type checking is not done in Ruby, but instead objects are assessed based on their ability to respond to particular methods, commonly called "Duck typing". In other words, if it responds to the methods you want, there's no reason to be particular about the type.

For example, object.is_a?(String) is too rigid since another class might implement methods that convert it into a string, or make it behave identically to how String behaves. object.respond_to?(:to_s) would be a better way to test that the object in question does what you want.

Function to find object type in Ruby

The assumption you've made is that if the value returned by a mathematical operation is an integer, the value's class will be Fixnum. That's not correct.

Take a look:

a = 5
puts a.class
# => Fixnum

b = 5.0
puts b.class
# => Float

Mathematically speaking, 5 and 5.0 are the same number and that number is an integer. But 5 and 5.0 in Ruby (like many other programming languages) are not the same. One is a fixed-point value (ergo Fixnum) and the other is a floating-point value (Float). A Fixnum can represent integers only, but a Float can represent both integers and fractions (but, it behooves me to mention, not all fractions).

In Ruby, when you do a mathematical operation with two Fixnums, a Fixnum is returned:

a = 4
puts a.class # => Fixnum

x = a ** 2
puts x # => 16
puts x.class # => Fixnum

However, if either number is a Float, a Float is returned:

a = 4

x = a ** 2.0
puts x # => 16.0
puts x.class # => Float

b = 4.0
puts b.class # => Float

y = b ** 2
puts y # => 16.0
puts y.class # => Float

y = b ** 2.0
puts y # => 16.0
puts y.class # => Float

You asked how to "find the type of an object," and the answer to that question is to use the Object#class method, as above. But as you can see, "Is the object a Fixnum?" and "Is the object an integer?" are two different questions.

If you want to know if a number in Ruby is an integer even if it's a Float, refer to the excellent answers to this question: Checking if a Float is equivalent to an integer value in Ruby

Checking variable type in Ruby

I think you are looking for Object#class. Here:

element = {}
element.class
# => Hash
a = []
a.class
# => Array

This will make your switch case as follows:

case element
when String
# do something
when Fixnum
# do something
when Hash
# do something
when Array
# do something
end

Note:
As mentioned by @ndn in comments below, case statement should not have .class in it (which I had initially in my answer). You can find the explanation here.

Is there a Ruby equivalent for the typeof reserved word in C#?

In addition to checking Object#class (the instance method class on the Object aka Base class), you could

s.is_a? Thing

this will check to see if s has Thing anywhere in its ancestry.

Checking the type of a method parameter

Use the Kernel#Integer method to convert the input before using it. It will raise an ArgumentError when the input could not be converted to an integer in any reasonable fashion.

def my_method(number)
number = Integer(number)
# do something with number, which is now guaranteed to be an integer
end

I recommend Avdi Grimm's new book Confident Ruby for more insight into this.

Discovering Ruby object members?

"foo".methods

See:

http://ruby-doc.org/core/classes/Object.html

http://ruby-doc.org/core/classes/Class.html

http://ruby-doc.org/core/classes/Module.html

Mimic another Ruby class so the object passes the === type check

This is a hackish solution that I warned against in my question:

Fixnum === page  #=> false

Numeric.extend Module.new {
def ===(obj)
obj.instance_of?(PageNumber) or super
end
}

Fixnum === page #=> true

It solves the problem but raises a question is it safe to do? I can't think of any drawbacks of this method from the top of my mind but since we're messing with a very important method here it might not be something we'd want to do.

Ruby - determining method origins?

Object#method returns a Method object giving meta-data about a given method. For example:

> [].method(:length).inspect
=> "#<Method: Array#length>"
> [].method(:max).inspect
=> "#<Method: Array(Enumerable)#max>"

In Ruby 1.8.7 and later, you can use Method#owner to determine the class or module that defined the method.

To get a list of all the methods with the name of the class or module where they are defined you could do something like the following:

obj.methods.collect {|m| "#{m} defined by #{obj.method(m).owner}"}

To which level returns a return inside a Proc Object in Ruby?

As a general rule, return always returns from the closest lexically enclosing method definition expression.

In this case, the closest lexically enclosing method definition expression is def a, therefore, return returns from a.

It does not actually matter that the return is inside a block in this case. The general rule is, well, general, so it applies regardless of where the return appears.

If we look more specifically at blocks, though, we can see that it still makes sense: in blocks, local variables are captured lexically, self is captured lexically, so it makes sense that return also behaves lexically. It is a general property of blocks that if you want to understand what is going on in a block, you only need to look lexically outwards.

And if we get even more specific, first going from the general rule to blocks, and now from blocks to Procs, the behavior still makes sense: a Proc is essentially a reified block, so it makes sense for a Proc to behave like a block.

There are some exceptions, though, to the general rule, and one important one are lambdas. Talking about lambdas in Ruby is always a little bit weird because lambdas are Procs but they behave differently from Procs. IMO, lambdas should have a separate class alongside Procs. Since lambdas are Procs, it makes it weird to talk about the differences between lambdas and Procs which are not lambdas (which don't have a standardized name and thus are confusingly also called Procs).

The behavior of a lambda differs from the behavior of a non-lambda Proc in two ways, one of which is relevant to your question:

  • Parameter binding in non-lambda Procs has the same semantics as parameter binding in blocks, whereas parameter binding in lambdas has the same semantics as parameter binding in message sends / method invocations.
  • In non-lambda Procs, return returns from the closest lexically enclosing method definition expression, just like in blocks, whereas in lambdas, return returns from the lambda itself, just like return in methods.

So, in both of these aspects, non-lambda Procs behave like blocks and lambdas behave like methods. I memorize it like this: "Proc" rhymes with "block" and both "lambda" and "method" are Greek.

As you probably know, there are some methods which also alter the behavior of blocks that are passed to them. E.g. instance_eval and instance_exec change the value of self, and define_method actually does change the behavior of return.

But since you didn't ask about blocks in general, and also didn't ask about lambdas specifically, and there are no reflective methods in your question, the general rules still applies to non-lambda Procs like the one shown in your question: return returns from the closest lexically enclosing method definition expression.



Related Topics



Leave a reply



Submit