Типы классов Ruby и case case

В чем разница между

case item.class
when MyClass
  # do something here
when Array
  # do something different here
when String
  # do a third thing
end

и

case item.class
when MyClass.class
  # do something here
when Array.class
  # do something different here
when String.class
  # do a third thing
end

По какой-то причине первая из этих работ иногда и вторая не работает, а в других случаях вторая работает, а первая - нет. Зачем? Какой из них "правильный" способ сделать это?

Ответ 2

Да, Накилон прав, вы должны знать, как работает трёхкамерный оператор === на объекте, указанном в предложении when. В Ruby

case item
when MyClass
...
when Array
...
when String
...

действительно

if MyClass === item
...
elsif Array === item
...
elsif String === item
...

Поймите, что этот случай вызывает трехмерный метод (например, MyClass.===(item)), и этот метод может быть определен для того, чтобы делать все, что вы хотите, а затем вы можете использовать оператор case с точностью w

Ответ 3

Вы можете использовать:

case item.class.to_s
    when 'MyClass'

... когда следующий поворот невозможен:

case item
    when MyClass

Причиной этого является то, что case использует ===, а отношение, описывающее оператор ===, не является коммутативным, Например, 5 является Integer, но есть Integer a 5? Вот как вы должны думать о case/when.

Ответ 4

В Ruby имя класса является константой, которая ссылается на объект типа Class, который описывает конкретный класс. Это означает, что выражение MyClass в Ruby эквивалентно произношению MyClass.class в Java.

obj.class - это объект типа Class, описывающий класс obj. Если obj.class MyClass, то obj было создано с использованием MyClass.new (грубо говоря). MyClass - объект типа Class, который описывает любой объект, созданный с помощью MyClass.new.

MyClass.class - это класс объекта MyClass (это класс объекта типа Class, который описывает любой объект, созданный с помощью MyClass.new). Другими словами, MyClass.class == Class.

Ответ 5

Это зависит от характера вашей переменной item. Если это экземпляр объекта, например

t = 5

затем

t.class == Fixnum

но если это сам класс, например,

t = Array

то это будет объект Class, поэтому

t.class == Class

EDIT: обратитесь к Как поймать Errno:: класс ECONNRESET в "случае, когда" ?, как указано Nakilon, так как мой ответ может быть неправильным.