2012-02-06 41 views
6

Tôi có ba đối tượng là tất cả cùng một lớp. Một được tạo ra thông qua Item.new và hai cái còn lại được lấy từ cơ sở dữ liệu (Mongoid). Tôi đang đi qua một/bất kỳ của các đối tượng này đến một phương pháp và kiểm tra các loại trong phương pháp mà qua is_a?:tại sao .is_a? và .class cho kết quả mâu thuẫn?

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

Vâng, tăng lương này là nhận được nhấn. Vì vậy, tôi kiểm tra lớp, is_a và instance_of trong giao diện điều khiển ray. Tôi nhận được kết quả mâu thuẫn. Tại sao họ có cùng một số class nhưng chỉ một trong số họ là instance_ofclass?

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

Có cách nào tốt hơn để kiểm tra loại đầu vào của tôi không? Tại sao ba điều đó là cùng một lớp không phải tất cả là trường hợp của lớp đó?

+0

* Họ có cùng lớp không? Ví dụ, các hiệp hội AR tự xưng là Array, nhưng chúng không. –

+1

Bạn có thể thêm đầu ra của 'i0.class.object_id' và tương tự cho các đối tượng khác không? Có thể nó có một cái gì đó để làm với các lớp tải lại và bạn có hai trường hợp khác nhau của cùng một lớp. –

+0

@DaveNewton ok, có cách nào tốt hơn để điều tra một lớp học và loại công cụ is_a? – jcollum

Trả lời

3

Tôi không biết Mongoid, nhưng thông thường, trong thư viện truy cập DB, bạn không lấy đối tượng thực sự ra khỏi cơ sở dữ liệu mà là đối tượng proxy hoạt động như một đối tượng cho đối tượng được lưu trữ trong DB. Vì Ruby thiếu các tính năng để thực hiện một proxy trong suốt hoàn hảo, đôi khi bạn sẽ thấy kết quả kỳ lạ, đặc biệt là khi sử dụng sự phản chiếu hoặc xung quanh nhận dạng đối tượng.

2

Lấy cảm hứng trên @ KL-7 bình luận, nó phải được xảy ra loại rằng:

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

Ya, cùng một vấn đề ở đây ...

Vấn đề giải quyết (bỏ qua) với sáng xấu xí:

i0.class.to_s==Item.to_s 
Các vấn đề liên quan