с чего бы .is_a?и .class дают противоречивые результаты? - PullRequest
6 голосов
/ 06 февраля 2012

У меня есть три объекта одного класса. Один был создан с помощью Item.new, а два других были извлечены из базы данных (Mongoid). Я передаю один / любой из этих объектов другому методу и проверяю тип в этом методе через is_a?:

def initialize (item, attrs = nil, options = nil)
  super(attrs, options)
  raise 'invalid item object' unless item.is_a?(Item)

Ну, этот рейз получил удар. Поэтому я проверяю класс is_a и instance_of в консоли rails. Я получаю противоречивые результаты. Почему у них одинаковые class, но только один из них будет instance_of, что class?

>> i0.is_a? Item
=> false
>> i1.is_a? Item
=> false
>> i2.is_a? Item
=> true

>> i0.class
=> Item
>> i1.class
=> Item
>> i2.class
=> Item

>> i0.instance_of?(Item)
=> false
>> i1.instance_of?(Item)
=> false
>> i2.instance_of?(Item)
=> true

Есть ли лучший способ сделать эту проверку типов моих входов? Почему три вещи одного класса не все являются экземплярами этого класса?

Ответы [ 3 ]

3 голосов
/ 06 февраля 2012

Я не знаю Mongoid, но обычно в библиотеке доступа к БД вы не получаете фактический объект из базы данных, а скорее прокси-объект, который выступает в качестве замены для объекта, хранящегося в БД , Поскольку в Ruby отсутствуют функции для реализации идеального прозрачного прокси-сервера, иногда вы можете увидеть странные результаты, особенно при использовании отражения или идентификации объекта.

2 голосов
/ 06 февраля 2012

Вдохновленный комментарием @ KL-7, это должно происходить примерно так:

class Item; end
class PseudoItem; end

# PseudodItem think it's an Item:
class << PseudoItem
  def inspect
    'Item'
  end
end

i0 = Item.new
i1 = PseudoItem.new

i0.class         #=> Item (correct!)
i1.class         #=> Item (wrong, due to redefinition of inspect!)

i0.is_a? Item    #=> true
i1.is_a? Item    #=> false, as it is a PseudoItem
0 голосов
/ 21 января 2014

Да, та же проблема здесь ...

Проблема решена (обойдена) с помощью некрасивого:

i0.class.to_s==Item.to_s
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...