if ( item::class == RPG::Weapon )
print \"yup\"
end
case item::class
when RPG::Item
type = 0
when RPG::Weapon
type = 1
when RPG::Armor
type =
Just case item
will be sufficient - no need for case item::class
.
Case matching in Ruby is done with a fuzzy matching (===
) algorithm that doesn't need such specific clauses.
Module#=== tests if the argument is an instance of self
. item.class
can never be an instance of anything but Class, in particular, it will never be an instance of either RPG::Weapon
or RPG::Armor
, therefore none of the when
branches will ever match and you will always get the else
branch.
By the way: using the namespace resolution operator ::
for message sends instead of the message sending operator .
is extremely un-idiomatic and confusing (and won't work for methods whose name starts with an uppercase character). In fact, I believe matz considers adding this feature to Ruby a mistake.
Note also that case
is an expression, in fact, everything in Ruby is an expression.
I would write the code as follows:
type = case item
when RPG::Item
0
when RPG::Weapon
1
when RPG::Armor
2
else
10
end
However, in general, conditionals are a code smell. Ruby is an object-oriented language, polymorphism (i.e. method dispatching based on the type of self
) is all the conditional you need! In fact, in this very example, you are manually examining the class of item
in order to determine its type, but that is exactly what method dispatch does anyway! Personally, I would refactor this code like this:
class RPG::Item
def type
0
end
end
class RPG::Weapon
def type
1
end
end
class RPG::Armor
def type
2
end
end
class RPG::Object # or whatever your baseclass is
def type
10
end
end
Now when you add a new kind of game object, you don't have to modify your existing code by adding a new branch to your case
expression. You just add the new class, without needing to modify any existing code.