为什么if
语句在下面的示例中起作用,而switch statement则没有。
工作:
if ''.class == String
puts "yep, that's a string"
end
不工作:
case ''.class
when String
puts "yep, that's a string, but this case is never triggered"
end
在上面的简单示例中,switch语句过度,但显然有一种情况是switch语句比DRyer链接elsif
答案 0 :(得分:11)
实际上,ruby的“案例”与===
进行比较所以你的例子相当于:
if ''.class === String
puts "yep, that's a string"
end
答案 1 :(得分:5)
快速简单的答案是案例使用===
(3等于)而不是2。
$ irb
if ''.class == String
puts "yep, that's a string"
end
是的,那是一个字符串
=> nil
if ''.class === String
puts "yep, that's a string"
end
=> nil
答案 2 :(得分:5)
这是因为case语句不使用==运算符,它使用===运算符(有时称为case equality运算符)。这取决于操作员左侧的内容。所以,如果你要像这样改变案例陈述:
case "Some string"
when String
puts "It's a string!"
else
puts "It's not a string!"
end
进入if语句,它将成为:
if String === "Some string"
puts "It's a string!"
else
puts "It's not a string!"
end
请注意,Ruby会根据您的预期执行向后,它会String === "Some string"
。这是因为您真正想要做的是在此处拨打Class#===
,而不是String#===
。 ===运算符对任何对象的作用都取决于类。在Class#===
的情况下,它大致相当于调用"Some string".is_a?(String)
。但是,如果您要执行"a" === "b"
,则String#===
方法大致相当于String#==
。
可以让人感到困惑,但运营商的使用很大程度上是惯用的。换句话说,“when语句中的类对象”惯用语意味着测试case对象是否属于该类。我写了一篇关于此的文章,它解释了一下,你可以阅读它here。
答案 3 :(得分:3)
正如其他人所说的,Ruby中的case
相等的工作方式与您预期的有所不同,所以您可以这样做
case foo
when String # that is, when String === foo, more or less when foo.class == String
do something
end
但一般来说,你不应该。如果您明确地测试类名,那么(通常)您的OO设计存在缺陷 - 在大多数情况下,您应该尝试使用多态。换句话说,而不是
if x.class == String
x.process_string
else
x.process_non_string
end
您应该只有x.process
,然后为process
和其他类定义String
。更清晰,更少的代码,不会强制调用者知道被调用对象的类。