Ruby类类型和case语句


135

之间有什么区别

case item.class
when MyClass
  # do something here
when Array
  # do something different here
when String
  # do a third thing
end

case item.class
when MyClass.class
  # do something here
when Array.class
  # do something different here
when String.class
  # do a third thing
end

出于某种原因,其中的第一个有时起作用而第二个则不起作用,而在另一些时候,第二个起作用而第一个不起作用。为什么?哪种方法是“正确”的方法?


1
字符串是一个类。班级的班级是班级。
Volte 2015年

请注意,MyClass === obj使用Module#===方法来检查是否obj是的实例MyClass
塞尔吉奥

Answers:


234

您必须使用:

case item
when MyClass
...

我遇到了同样的问题: 如何在“ case when”情况下捕获Errno :: ECONNRESET类?


1
谢谢!对不起,我很抱歉(或某种程度的欺骗),但几次搜索都没有发现上一个问题。看来,case语句使用===是一个很普遍的问题,现在我看到这就是问题所在。在教程之类的东西中应该经常指出这一点(但是我敢打赌,许多教程的作者也不知道这一点)。
黛西·索菲亚·霍尔曼

4
使用ActiveRecord时未提及的警告。类比较中的ActiveRecord ===方法使用.is_a ?,这意味着类的子类在case语句中将评估为true。github.com/rails/rails/blob/…–
杰里米·贝克

60

是的,Nakilon是正确的,您必须知道Threequal ===运算符如何在when子句中给定的对象上工作。在Ruby中

case item
when MyClass
...
when Array
...
when String
...

是真的

if MyClass === item
...
elsif Array === item
...
elsif String === item
...

了解该案例正在调用Threequal方法(MyClass.===(item)例如),并且可以定义该方法以执行所需的任何操作,然后可以使用带有precisionw的case语句


如果有的arr = []话,我注意到if Array === arr它将评估为true但if arr === Array将评估为false。有人可以帮忙解释一下吗?
丹尼尔(Daniel)

4
===只是一种方法,可以将其定义为执行类设计人员希望其执行的任何操作。同样要记住,a === b确实意味着a。=== b,因此,如果前后切换a和b,则会得到不同的行为。不能保证===是可交换的。实际上,Array === Array为false,而Object === Object为true,因此Array重新定义了===的语义。
2013年

13

您可以使用:

case item.class.to_s
    when 'MyClass'

...当无法进行以下扭曲时:

case item
    when MyClass

这样做的原因是case使用===,并且操作员描述的关系不是可交换的===。例如,5是一个Integer,而是Integer一个5?这就是您应该想到case/的方式when


5

在Ruby中,类名是一个常量,它引用Class描述特定类的类型的对象。这意味着MyClass在Ruby 中说等同于MyClass.class在Java中说。

obj.classClass描述类别的类型的对象obj。如果obj.classMyClass,则obj使用MyClass.new(大致而言)创建。MyClass是类型的对象,Class它描述使用创建的任何对象MyClass.new

MyClass.class是类的MyClass对象(它的类型的对象的Class描述使用创建的任何对象MyClass.new)。换句话说,MyClass.class == Class


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.