【翻译】Ruby’s case statement – advanced techniques

没有什么比case语句更加的简单和无聊了。这是沿袭自C语言,通常被用来代替一系列的if语句。实际上,Ruby中的case语句比你想象的要更加的丰富和更加的复杂,让我们来看一下下面的这个例子。

Ruby Code:
case "Hi there"
when String
  pute "case statements match class"
end
# outputs: "case statements match class"

这个例子表明case语句不仅匹配一个条目的值,并且还能匹配其class。这可能是因为Ruby内部使用了===操作符。

快速浏览===操作符

当你用Ruby写下x===y,你就是在询问y是属于x所代表的组吗?这是一个非常通用的语句,它的定义会依据你所处理的组别而改变。

Ruby Code:
# Here, the Class.===(item) method is called, which returns true if item is an instance of the class

String === "hello" # true
String === 1 # false

字符串,正则表达式以及区间都定义了各自的===方法,表现上大抵和你的预期相符合,你甚至可以在你自己的类中增加一个===方法。现在我们懂得了这些,我们可以变出各种各样的戏法。

case语句中的区间匹配

你之所以能够在case语句中使用区间,是因为range === n 返回的是range.include?(n)。我为什么这肯定呢?这是因为文档中已经写明了。

Ruby Code:
case 5
when (1..10)
  puts "case statements match inclusion in a range"
end

# outputs "case statements match inclusion in a range"

case语句中的正则表达式匹配

在case语句中使用正则也是可能的,因为/regexp/ === “string”返回true,当且仅当字符串匹配该正则表达式时。正则表达式的文档对其做出了解释。
Ruby Code:
case “FOOBAR”
when /BAR$/
puts “they can match regular expressions!”
end

# outputs "they can match regular expressions!"

匹配proc和lambda

这是非常奇怪的一类,当你使用Proc#===(item),就和Proc#call(item)一样。这是定义的文档,这个文档的意思是你可以通过动态匹配在case语句中使用proc和lambda。
Ruby Code:
case 40
when -> (n) { n.to_s == “40” }
puts “lambdas!”
end

# outputs "lambdas"

另外的写法:

Ruby Code:
 odd  = proc(&:odd?)
 even = proc(&:even?)
  case number
  when odd
    puts "Odd number"
  when even
    puts "Even number"
  end

编写你自己的匹配类

就像我上文提到的那样,在你自己的类中增加一个自定义的case行为就和你定义一个===方法一样简单。使用这项技术能够讲一系列复杂的条件逻辑拆分成多个较小的类。
Ruby Code:
class Success
def self.===(item)
item.status >= 200 && item.status < 300
end
end

class Empty
  def self.===(item)
    item.response_size == 0
  end
end

case http_response
when Empty
  puts "response was empty"
when Success
  puts "response was a success"
end

Extra

另外还可以在when语句中增加多个可以匹配的值。

Ruby code:
print "Enter your grade: "
grade = gets.chomp
case grade
when "A", "B"
  puts 'You pretty smart!'
when "C", "D"
  puts 'You pretty dumb!!'
else
  puts "You can't even use a computer!"
end

什么时候不该用case/when语句

  当你只有一些简单的1:1映射关系的时候,不该使用该方法。

Ruby code:
  case country
  when "europe"
    "http://eu.example.com"
  when "america"
    "http://us.example.com"
  end


下面是比较好的写法:


Ruby code:
   SITES = {
     "europe"  => "http://eu.example.com",
     "america" => "http://us.example.com"
   }
   SITES[country]

原文:

参考: