我正在使用Ruby 1.9.2和Ruby on Rails 3.2.2。我有以下方法:
# Note: The 'class_name' parameter is a constant; that is, it is a model class name.
def my_method(class_name)
case class_name
when Article then make_a_thing
when Comment then make_another_thing
when ... then ...
else raise("Wrong #{class_name}!")
end
end
我想了解为什么在上面的case
语句中,当我执行else
,my_method(Article)
之类的方法调用时,它始终运行my_method(Comment)
“部分”等等。
我该如何解决这个问题?有人有建议如何处理这个吗?
答案 0 :(得分:4)
这是因为case
调用了===
,而===
on Class(或者具体是模块,Class从哪个类开始)是这样实现的:
mod === obj
→true
或false
案例平等 - 如果
true
是obj
的实例或mod
的后代之一,则返回mod
。模块的用途有限,但可以在case语句中用于按类对对象进行分类。
这意味着除了Class
&之外的任何常数。 Module
{例如Foo
),Foo === Foo
始终返回false
。因此,您始终会在else
声明中获得case
条件。
相反,只需使用对象本身而不是其类调用case
,或使用if
语句。
答案 1 :(得分:3)
将对象引用传递给方法,就像在后台使用===运算符一样,因此这些将失败。 e.g。
obj = 'hello'
case obj.class
when String
print('It is a string')
when Fixnum
print('It is a number')
else
print('It is not a string')
end
另一方面,这很好用:
obj = 'hello'
case obj # was case obj.class
when String
print('It is a string')
when Fixnum
print('It is a number')
else
print('It is not a string')
end
请参阅“如何在Ruby中编写switch语句”https://stackoverflow.com/a/5694333/1092644
的相关答案答案 2 :(得分:1)
如果您只想比较名称的相等性,可以将to_s
添加到类常量。
def my_method(class_name)
case class_name.to_s
when 'Article'
make_a_thing
when 'Comment'
make_another_thing
... ...
end
end