Ruby:为什么Hash === {}会返回true?

时间:2014-09-18 20:07:17

标签: ruby

我有一个哈希,让我们说:

ahash = {test1: "test1", test2: "test2"}

为什么Hash === ahash返回true,但ahash === Hash不返回?这是带有===和类名的默认ruby行为吗?

2 个答案:

答案 0 :(得分:17)

这就是===方法的工作原理。它具有方向性,适用于任何类:

"foo" === String
# => false
String === "foo"
# => true

这是因为评估结果为:

"foo".send(:===, String)
String.send(:===, "foo")

这是两种不同的方法,一种用于类,一种用于实例。

如果您只关注课程信息:

"foo".is_a?(String)
# => true

{ }.is_a?(Hash)
# => true

这种方法使你的意图更清晰。

答案 1 :(得分:6)

您没有测试您认为正在测试的内容

Module#===(也称为“case equality operator”)如果表达式右侧的对象是左侧的一个实例或其后代之一,则返回true。当你问:

Hash === {test1: "test1", test2: "test2"}

你真正要问的是:“这个哈希文字是Hash类的一个实例还是后代?”另一方面,反之则不然,因为Hash 不是散列文字的实例或后代。

关于案例平等的更多信息

另一方面,以下方式有效:

Hash.new === {}
{} === Hash.new

因为两个表达式都是大小写相同的。以下是使用您的数据的相同结果:

Hash[:test1, "test1", :test2, "test2"] === {:test1=>"test1", :test2=>"test2"}
#=> true

{:test1=>"test1", :test2=>"test2"} === Hash[:test1, "test1", :test2, "test2"]
#=> true

但是,三等分不仅仅是Object#is_a?的替身。它实际上是由case / when语句和Giles Bowkett says

使用
  

===方法用于控制case / when块如何评估对象。它永远不应该被人类使用。编写的代码是由其他代码使用的,具体地说,是通过大小写和何时使用。