1. Computing

On 'case' and 'class'

By

While dynamic programming and duck typing often make it a bad idea to do so, it's sometimes useful to do different things based on the type of a given variable. For example, if the type of a variable is a URL, fetch that URL, otherwise, open it as a file. There are usually better ways of doing things, but this is often the most direct way.

The following is a common mis-step in implementing this. The author has the right idea, but has missed something.

#!/usr/bin/env ruby

num = 10

case num.class
when Numeric
  puts "Right class"
else
  puts "Wrong class"
end

What is the output? The output is "Wrong class", but why? To answer this, you first have to know how the case construct works. It'll go down the list of 'when' statements and, for each when statement's argument, compare the object given with the case statement to the object given with the when statement using the === operator. In this example, it will run Numeric === num.class.

But what does === do? It depends on what's on the left side. In this case, it's a class, so it will use Module#===, which will return true if the right side is an instance of, or subclass of, the left side. See what went wrong now? What we're really doing when we say Numeric === num.class is Numeric === Numeric. Is the class Numeric an instance of, or subclass of, Numeric? No, Numeric is a Class, so the comparison will evaluate to false.

It should be obvious what went wrong here now. Instead of using num.class in the case statement, num should be used. Then, the comparison would read as Numeric === num, and since num is an instance of, or instance of a subclass of, Numeric, the comparison will evaluate to true. Below is the full working code.

#!/usr/bin/env ruby

num = 10

case num
when Numeric
  puts "Right class"
else
  puts "Wrong class"
end

See More About
  1. About.com
  2. Computing
  3. Ruby
  4. Beginning Ruby
  5. On 'case' and 'class'

©2014 About.com. All rights reserved.