2012-06-28 37 views
5

Tôi có một lớp bao bọc xung quanh một số đối tượng mà tôi muốn sử dụng làm khóa trong Hash. Các đối tượng bọc và unwrapper nên ánh xạ tới cùng một khóa.Kiểm tra bình đẳng nào mà Hash của Ruby sử dụng khi so sánh các khóa?

Một ví dụ đơn giản sẽ là thế này:

class A 
    attr_reader :x 
    def initialize(inner) 
    @inner=inner 
    end 
    def x; @inner.x; end 
    def ==(other) 
    @inner.x==other.x 
    end 
end 
a = A.new(o) #o is just any object that allows o.x 
b = A.new(o) 
h = {a=>5} 
p h[a] #5 
p h[b] #nil, should be 5 
p h[o] #nil, should be 5 

Tôi đã thử ==, ===, eq? và băm tất cả để không có kết quả.

+1

Bạn có thể muốn nhìn vào 'SimpleDelegator', nếu bạn muốn giao phó hầu hết các phương pháp để '@ inner'. –

+0

Cảm ơn @ Marc-AndréLafortune! Đã học một cái gì đó mới ngày hôm nay – alexloh

Trả lời

4

Hash sử dụng key.eql? để kiểm tra các phím cho sự bình đẳng. Nếu bạn cần sử dụng trường hợp của các lớp học của riêng bạn làm khóa trong Hash, bạn nên chọn để xác định cả eql? và phương thức băm. Phương thức băm phải là có thuộc tính a.eql? (B) ngụ ý a.hash == b.hash.

Vậy ...

class A 
    attr_reader :x 
    def initialize(inner) 
    @inner=inner 
    end 
    def x; @inner.x; end 
    def ==(other) 
    @inner.x==other.x 
    end 

    def eql?(other) 
    self == other 
    end 

    def hash 
    x.hash 
    end 
end 
+0

Ah, vì vậy nó sử dụng cả hai. Bây giờ tôi nghĩ về nó, làm cho tinh thần để sử dụng 'băm' để có được xô sau đó' eql? 'Cho các thử nghiệm thực tế. Tôi nghĩ rằng nó cũng giống nhau trong Java quá – alexloh

+0

Nhưng tại sao việc thực hiện mặc định 'eq? 'Không sử dụng' == '? – ony

Các vấn đề liên quan