为什么会这样.is_a?和.class给出相互矛盾的结果?

时间:2012-02-06 16:53:34

标签: ruby

我有三个属于同一个类的对象。一个是通过Item.new创建的,另外两个是从数据库中提取的(Mongoid)。我将一个/任何这些对象传递给另一个方法并通过is_a?检查该方法中的类型:

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

嗯,这次加薪受到了打击。所以我在rails控制台中检查了类,is_a和instance_of。我的结果相互矛盾。为什么他们会有相同的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 个答案:

答案 0 :(得分:3)

我不知道Mongoid,但通常,在数据库访问库中,您不会从数据库中获取实际对象,而是作为存储在数据库中的对象的替代的代理对象。由于Ruby缺乏实现完美透明代理的功能,因此有时会看到奇怪的结果,尤其是在使用反射或围绕对象标识时。

答案 1 :(得分:2)

受到@ 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

答案 2 :(得分:0)

雅,这里同样的问题......

问题已解决(绕过)丑陋:

i0.class.to_s==Item.to_s