Типы классов Ruby и операторы case - PullRequest
122 голосов
/ 11 октября 2010

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

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

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

Ответы [ 5 ]

205 голосов
/ 11 октября 2010

Вы должны использовать:

case item
when MyClass
...

У меня была такая же проблема: Как перехватить класс Errno :: ECONNRESET в "case when"?

53 голосов
/ 11 октября 2010

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

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

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

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

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

9 голосов
/ 10 апреля 2015

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

case item.class.to_s
    when 'MyClass'

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

case item
    when MyClass

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

5 голосов
/ 11 октября 2010

В 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.

1 голос
/ 11 октября 2010

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

t = 5

, тогда

t.class == Fixnum

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

t = Array

, тогда он будетбыть Class объектом, поэтому

t.class == Class

РЕДАКТИРОВАТЬ : пожалуйста, обратитесь к Как перехватить класс Errno :: ECONNRESET в «case when»?Накилоном, так как мой ответ может быть неправильным.

...