2010-10-15 10 views
5

Betrachten Sie dieses:Vergleicht man Objekte in Ruby

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 

Gibt es eine Möglichkeit, wenn alle öffentlichen Attribute gleich in Klassen von gleicher Art sind zu überprüfen?

Antwort

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

Aber was, wenn ich das mit anderen Klassen machen möchte? Oder wenn es 100 Attribute gibt? – dfens

+4

In Ihrer == (anderen) Methode könnten Sie self.instance_variables.each do | ivar | self.ivar == other.ivar end Vielleicht möchten Sie auch === sehen. –

+0

hat für mich funktioniert, danke – dfens

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 definiert ==, eql? und hash für Sie, so dass zwei Aaa s gleich sind, wenn ihre Werte für a und b gleich sind. Es definiert auch initialize, so dass Sie optional die Werte für a und b beim Erstellen des Objekts (Aaa.new(value_for_a, value_for_b)) übergeben können. Und es definiert to_a, um [a,b] zurückzugeben.

Sie können auch Struct.new mit einem Block verwenden, um zusätzliche Methoden zu definieren, so dass Sie die volle Leistung einer „normalen“ Klasse haben:

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

Das scheint in Ordnung, aber ich brauche diese Funktionalität für Objekte, trotzdem nette Antwort, die ich nicht über Structs wusste – dfens

+1

@dfens: Das sind Objekte. 'Struct.new' ist nur eine Fabrikmethode für Klassen. Sie würden das gleiche Verhalten erhalten, wenn Sie 'Aaa' mit dem Schlüsselwort' class' definieren und dann '==' usw. selbst definieren würden. – sepp2k

0

zusätzliche Methode zu behandeln Objekte in Ruby Vergleich besteht in der Verwendung von hash. Aus Performance Grund, wenn die Klasse sehr groß sind, ist die beste hash zu verwenden Rubin-Objekte als so vergleichen:

Klasse Aaa attr_accessor: a, b

def intialize (value_a, value_b) @a = value_a @b = value_b Ende

def hash (Ziel) @ a.hash == target.a.hash & & @ b.hash == target.b.hash Ende Ende

A = new Aaa ('was auch immer', 'wann immer') B = new Aaa ('aber', 'wer') A.hash (B)

1

Wir können auf eine beliebige Anzahl von Instanzen leicht verallgemeinern und legen Sie die Voraussetzung für die Getter für die Instanzvariablen:

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 

ändern z zu:

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

dann: