Ruby` when'关键字在case语句中不使用==。它有什么用?

时间:2010-09-21 06:28:23

标签: ruby case

x == User会返回true,但case x语句不会运行与User关联的块。这里发生了什么?

u = User.new
# => #<User:0x00000100a1e948>

x = u.class
# => User

x == User
# => true

case x
when User
  puts "constant"
when "User"
  puts "string"
else
  puts "nothing?"
end
# => nothing?

2 个答案:

答案 0 :(得分:21)

案例比较使用===而不是==。对于许多对象,=====的行为相同,请参阅NumericString

5 == 5 #=> true
5 === 5 #=> true

"hello" == "hello" #=> true
"hello" === "hello" #=> true

但是对于其他类型的对象===可能意味着许多事情,完全取决于接收者。

对于类的情况,===测试对象是否是该类的实例:

Class === Class.new #=> true. 

对于Range,它会检查对象是否属于该范围:

(5..10) === 6 #=> true

对于Procs,===实际上调用了Proc

multiple_of_10 = proc { |n| (n % 10) == 0 }
multiple_of_10 === 20 #=> true (equivalent to multiple_of_10.call(20))

对于其他对象,请检查其===的定义以揭示其行为。它并不总是很明显,但它们通常会产生某种意义..

以下是将所有内容放在一起的示例:

case number
when 1
    puts "One"
when 2..9
    puts "Between two and nine"
when multiple_of_10
    puts "A multiple of ten"
when String
    puts "Not a number"
end  

有关详细信息,请参阅此链接:http://www.aimred.com/news/developers/2008/08/14/unlocking_the_power_of_case_equality_proc/

答案 1 :(得分:2)

在case语句中,使用===运算符进行比较。

所以你的代码被翻译成以下内容:

case x
when User === x 
    puts "Constant"
when "User" === x
    puts "string"
else 
    puts "nothing"
end

不同的类以不同的方式定义===

Class类定义===,以便它测试右手操作数(x)是否是左手操作数(User)命名的类的实例。因此,将User === x评估为false并不奇怪。相反,User === u(u = User.new)为true

irb(main):001:0> class User
irb(main):002:1> end
=> nil
irb(main):003:0> u = User.new
=> #<User:0xb7a90cd8>
irb(main):004:0> User === u.class
=> false
irb(main):005:0> User === u
=> true