Подтвердить что ты не робот

Ruby: Почему Hash === {} возвращает true?

У меня есть хэш, скажем:

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

Почему это, что Hash === ahash возвращает true, но ahash === Hash нет? Является ли это некоторым поведением рубина по умолчанию с === и именем класса?

4b9b3361

Ответ 1

Как работает метод ===. Он направлен и применяется к любому классу:

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

Это потому, что это оценивается как:

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

Это два разных метода: один для класса, один для экземпляра.

Если вы интересуетесь только информацией о классе:

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

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

Этот метод значительно упрощает ваше намерение.

Ответ 2

Вы не тестируете, что думаете, что тестируете

Модуль # === (также называемый "оператор равенства случая" ) возвращает 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

Однако, триquals - это не просто stand-in для Object # is_a?. Это действительно предназначалось для потребления в случаях/когда заявления, а Джайлс Бокетт говорит:

Существует метод === для управления тем, как блок/блок будет оценивать объект. Он никогда не должен использоваться людьми. Это код, написанный для потребления другим кодом, в частности, в случае и когда.