=== vs. == в Ruby

В Ruby, в чем разница между == и ===? RDoc говорит

Case Equality - для класса Object, фактически то же самое, что вызов # ==, но обычно переопределяется потомками, чтобы обеспечить содержательную семантику в операторах case.

Является #== такой же как ==? И не могли бы вы привести пример, когда / как это используется в кейсах?

3 ответа

Решение

Два действительно не имеют ничего общего друг с другом. Особенно, #== является оператором равенства и #=== не имеет ничего общего с равенством. Лично я считаю весьма прискорбным, что #=== выглядит так похоже на #==, использует знак равенства и часто называется оператором равенства случаев, операторомтройного равенства или оператором трехзначностей, когда он действительно не имеет ничего общего с равенством.

Я звоню #=== оператор подстановки дел (это лучшее, что я мог придумать, я открыт для предложений, особенно от носителей английского языка).

Лучший способ описать a === b это "если у меня есть ящик с надписью aимеет ли смысл ставить b в этом?"

Так, например, Module#=== проверяет ли b.is_a?(a), Если у вас есть Integer === 2имеет ли смысл ставить 2 в коробке с надписью Integer? Да, это так. Как насчет Integer === 'hello'? Очевидно нет.

Другой пример Regexp#===, Это тесты на совпадение. Есть ли смысл ставить 'hello' в коробке с надписью /el+/? Да, это так.

Для коллекций, таких как диапазоны, Range#=== определяется как тест членства: имеет смысл поместить элемент в поле, помеченное коллекцией, если этот элемент находится в коллекции.

Итак, вот что #=== has: проверяет, может ли аргумент быть отнесен к получателю.

Какое это имеет отношение к case выражения? Просто:

case foo
when bar
  baz
end

такой же как

if bar === foo
  baz
end

Да, по #== документы означают "метод экземпляра" == текущего объекта ".

=== используется в утверждениях case как таковых:

case obj
when x
  foo
when y
  bar
end

Такой же как

if x === obj
  foo
elsif y === obj
  bar
end

Некоторые классы, которые определяют свои собственные === Диапазон (действовать как include?), Класс (вести себя как obj.is_a?(klass)) а также Regexp (вести себя как =~ кроме возврата логического). Некоторые классы, которые не определяют свои собственные === числовые классы и String.

Так

case x
when 0
  puts "Lots"
when Numeric
  puts(100.0 / x)
when /^\d+$/
  puts(100.0 / x.to_f)
default
  raise ArgumentError, "x is not a number or numeric string"
end

такой же как

if 0 == x
  puts "Lots"
elsif x.is_a? Numeric
  puts(100.0 / x)
elsif x =~ /^\d+$/
  puts(100.0 / x.to_f)
else
  raise ArgumentError, "x is not a number or numeric string"
end

Интересный факт, === также используется для сопоставления исключений в rescue

Вот пример

class Example
  def self.===(exception)
    puts "Triple equals has been called."
    true
  end
end

raise rescue Example
# => prints "Triple equals has been called."
# => no exception raised

Это используется для соответствия системным ошибкам.

SystemCallError.=== было определено, чтобы возвращать истину, когда два имеют одинаковое значение errno. С помощью этого системного вызова ошибки с тем же номером ошибки, такие как Errno::EAGAIN а также Errno::EWOULDBLOCK, оба могут быть спасены, перечислив только один из них.

Другие вопросы по тегам