case 表达式的高级技巧

通常我们对 case 表达式的理解是用它来替换一大堆的 if 判断,那么它还有啥技巧呢?

case "Hi there"
when String
  puts "case statements match class"
end

# outputs: "case statements match class"

因为 Ruby 的 case 表达式内部使用的是 === 进行条件判断,所以先来一起复习下 === 的用法。

=== 运算符简介

可以先复习一下这里

  • 如果是类来调用 === 方法,就会比较另一个对象是否为当前类的实例
  • 如果是对象调用 === 方法,和 == 用法相同,仅比较两个值是否相等
# Here, the Class.===(item) method is called, which returns true if item is an instance of the class

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

字符串,范围,正则表达式都定义了自己的 ===(item) 方法,它们的工作方式也和我们期待的一样。我们也可以给自己定义的类增加 ===(item) 方法。

使用范围进行匹配验证

range === n 等于 range.include?(n)

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

# outputs "case statements match inclusion in a range"

使用正则表达式进行匹配验证

/regexp/ === "string"

case "FOOBAR"
when /BAR$/
  puts "they can match regular expressions!"
end

# outputs "they can match regular expressions!"

使用 procslambdas 进行匹配验证

这里需要注意的是 Proc#===(item) 等价于 Proc#call(item)。这意味着你可以使用 procslambdas 进行动态的匹配。

case 40
when -> (n) { n.to_s == "40" }
  puts "lambdas!"
end

# outputs "lambdas"

创建自己的匹配类

正如前文提到的,我们可以通过在类里面添加 === 方法,创建自己的匹配类。这样的好处是可以拆分我们的业务逻辑到多个细小的类。

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

如果觉得我的文章对您有用,请在支付宝公益平台找个项目捐点钱。 @Victor Jan 10, 2016

奉献爱心