2010-10-15 240 views
5

考慮一下:對象的比較

class Aaa 
    attr_accessor :a, :b 
end 

x = Aaa.new 
x.a, x.b = 1,2 
y = Aaa.new 
y.a, y.b = 1,2 

puts x == y #=>false 

有一些方法,以檢查是否所有的公共屬性是相同類型的類一樣的嗎?

回答

6
class Aaa 
    attr_accessor :a, :b 

    def ==(other) 
    return self.a == other.a && self.b == other.b 
    end 
end 

x = Aaa.new 
x.a,x.b = 1,2 
y = Aaa.new 
y.a,y.b = 1,2 
y = Aaa.new 
y.a,y.b = 1,2 
z = Aaa.new 
z.a,z.b = 1,3 

x == y # => true 
x == z # => false 
+0

但是如果我想用其他類來做這件事呢?或者如果有100個屬性? – dfens 2010-10-16 17:33:09

+4

在你的==(其他)方法中,你可以做self.instance_variables.each do | ivar | self.ivar == other.ivar end 您可能也想看看===。 – 2010-10-17 01:07:00

+0

爲我工作,謝謝 – dfens 2010-10-19 16:41:52

8
Aaa = Struct.new(:a, :b) 

x = Aaa.new 
x.a, x.b = 1,2 
y = Aaa.new 
y.a, y.b = 1,2 

x == y #=> true 

Struct定義==eql?hash給你,所以兩個Aaa s爲相等的,如果他們對ab值相等。它還定義了initialize,以便在創建對象(Aaa.new(value_for_a, value_for_b))時可以選擇傳遞ab的值。它定義to_a返回[a,b]

您還可以使用Struct.new與塊定義額外的方法,讓你有一個「正常」類的全功率:

Aaa = Struct.new(:a, :b) do 
    def c 
    a+b 
    end 
end 
Aaa.new(23,42).C#=> 65 
+0

這似乎很好,但我需要對象的這種功能,無論如何,我不知道結構很好的迴應 – dfens 2010-10-15 10:16:07

+1

@dfens:那些是對象。 'Struct.new'只是類的工廠方法。如果你使用'class'關鍵字定義'Aaa',然後自己定義'=='等,你會得到完全相同的行爲。 – sepp2k 2010-10-15 10:28:04

0

額外的方法來處理在Ruby中比較的對象包括在使用hash。出於性能方面的原因,當類是巨大的,最好是用hash比較Ruby對象像這樣:

AAA級 attr_accessor:一,:乙

高清intialize(value_a,value_b) @a = value_a @b = value_b 端

DEF散列(目標) @ a.hash == target.a.hash & & @ b.hash == target.b.hash 端 端

A =新的AAA( '無論', '每當') B =新的AAA( '然而', '誰') A.hash(B)

1

我們可以很容易地推廣到任意數量的實例並放棄對干將要求的實例變量:

class Aaa 
    def initialize(a,b,c) 
    @a, @b, @c = a, b, c 
    end 
end 

x = Aaa.new(1,2,3) 
y = Aaa.new(1,2,3) 
z = Aaa.new(1,2,3) 
arr = [x,y,z] 

x.instance_variables.map do |v| 
    arr.map { |i| i.send(:instance_variable_get,v) }.uniq.size == 1 
end.all? 
    #=>true 

更改z到:

z = Aaa.new(1,2,4) 

則:

x.instance_variables.map do |v| 
    arr.map { |i| i.send(:instance_variable_get,v) }.uniq.size == 1 
end.all? 
    #=> false