为什么 switch 语句执行相等测试的方式与 if 语句不同?
为什么 if
语句在下面的示例中有效,而 switch 语句 没有。
工作:
if ''.class == 字符串 放“是的,那是一个字符串” 结尾
不工作:
case ''.class 当字符串 提出“是的,这是一个字符串,但这种情况永远不会触发” 结尾
在上面的简单示例中,switch 语句有点过分了,但显然在某些情况下 switch 语句比链接的 elsif 更干燥
Why does the if
statement work in the example below while the switch statement does not.
working:
if ''.class == String puts "yep, that's a string" end
not working:
case ''.class when String puts "yep, that's a string, but this case is never triggered" end
In the trivial example above, the switch statement is overkill, but there are obviously situations where a switch statement would be DRYer than chained elsif
s
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
实际上,ruby 的“case”与 === 进行比较,
因此您的示例相当于:
Actually, ruby's "case" makes the comparaison with ===
So your example is equivalent to :
这是因为 case 语句不使用 == 运算符,而是使用 === 运算符(有时称为 case 相等运算符)。其作用取决于操作符左侧的内容。因此,如果您将这样的 case 语句转换
为 if 语句,它将变成这样:
请注意,Ruby 会按照您期望的方式向后执行此操作,它会
String == =“一些字符串”
。这是因为您真正想要做的是在这里调用Class#===
,而不是String#===
。 === 运算符对任何对象的作用实际上取决于类。对于Class#===
,它大致相当于调用"Some string".is_a?(String)
。但如果您要执行"a" === "b"
,则String#===
方法大致相当于String#==.
它可能会令人困惑,但操作符的用法很大程度上是惯用的。换句话说,“when 语句中的类对象”习惯用法意味着测试 case 对象是否属于该类。我写了一篇对此进行了更多解释的文章,您可以阅读它 这里。
This is because the case statement doesn't use the == operator, it uses the === operator (sometimes called the case equality operator). What this does varies depending on what's on the left side of the operator. So, if you were to transform case statement like this:
Into an if statement, it would become this:
Note that Ruby does this backwards from how you'd expect, it does
String === "Some string"
. This is because what you really want to do is callClass#===
here, and notString#===
. What the === operator does for any object is really up to the class. In the case ofClass#===
, it's roughly equivalent to calling"Some string".is_a?(String)
. But if you were to do"a" === "b"
, theString#===
method is roughly equivalent toString#==
.It can get confusing, but the operator's usage is largely idiomatic. In other words, the "class object in a when statement" idiom means to test if the case object is of that class. I've written an article on this that explains it a bit more, you can read it here.
快速而简单的答案是 case 使用
===
(3 等于)而不是 2。The quick and simple answer is that case uses
===
(3 equals) and not two.正如其他人所说,Ruby 中的
case
相等性的工作方式与您的预期略有不同,因此您可以这样做,但通常,您不应该。如果您显式地测试类名,那么(通常)您的 OO 设计就有缺陷——在大多数情况下,您应该尝试使用多态性。换句话说,
您应该简单地拥有
x.process
,然后为String
和其他类定义不同的process
。更干净、更少的代码,不会强迫调用者知道被调用对象的类。As others have said,
case
equality in Ruby works a bit differently than you might expect, so you can just doBut generally, you shouldn't. If you're explicitly testing class names, then (usually) your OO design is flawed -- in most cases, you should try to use polymorphism instead. In other words, instead of
you should simply have
x.process
, and then defineprocess
differently forString
and other classes. Cleaner, less code, doesn't force the caller to know the class of the called object.