【问题标题】:Why does "foo".class === String return false?为什么“foo”.class === String 返回 false?
【发布时间】:2015-11-30 23:43:25
【问题描述】:
当这没有按预期工作时,我开始好奇:
var = "foo"
case var.class
when String
puts "bar"
else
puts "baz"
=> "baz"
我知道 case 语句使用的是 ===,但我不明白 === 做了什么。文档说...
大小写相等 – 对于类 Object,实际上与调用 #== 相同,
但通常会被后代覆盖以提供有意义的
case 语句中的语义。
http://ruby-doc.org/core-2.2.3/Object.html#method-i-3D-3D-3D
这是否意味着 Class(或其模块之一)中的 === 会覆盖 Object 中的 ===?我很困惑。
【问题讨论】:
标签:
ruby
string
boolean
equality
【解决方案1】:
=== 被 Class 对象(更一般地,Module objects)覆盖,表示“右侧是左侧的实例”。
例如:
>> String === ""
=> true
>> Class === String
=> true
这是不直观的,但这是真的。但是,它确实使您尝试做的事情变得更短:
var = "foo"
case var
when String
puts "bar"
else
puts "baz"
end
# outputs "bar", since String === "foo"
这就是您的尝试失败的原因:Ruby 计算 String === String,这是错误的,因为 String 类本身不是字符串。
【解决方案2】:
您在这里与case equality 打交道。在这里,它被后代覆盖以提供有意义的语义。在这种情况下,Module 会覆盖它。
Case Equality — 如果对象是模块的实例或模块的后代之一,则返回 true。对模块的使用有限,但可用于 case 语句按类对对象进行分类。
在模块中,=== 的作用类似于 Ruby 的 is_a? 方法。
在您的情况下,它返回 false,因为 "Foo".class 不是字符串类的实例。
"Foo".class.is_a?(String)
=> false
【解决方案3】:
这与如何为类实现大小写等价运算符=== 有关。使用对象,而不是 object.class
var = "foo"
case var
when String
puts "bar"
else
puts "baz"
=> "bar"