2010-10-15 19 views
5

Considerate questo:Confrontando oggetti in rubino

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 

c'è qualche modo per verificare se tutti gli attributi pubblici sono uguali in classi dello stesso tipo?

risposta

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

Ma cosa succede se voglio farlo usando altre classi? O se ci sono 100 attributi? – dfens

+4

Nel tuo == (altro) metodo, potresti fare self.instance_variables.each do | ivar | self.ivar == other.ivar end Si potrebbe anche voler guardare ===. –

+0

ha funzionato per me, grazie – 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 definisce ==, eql? e hash per te, in modo che due Aaa s sono uguali, se il loro valore per a e b sono uguali. Definisce inoltre initialize in modo che sia possibile passare facoltativamente i valori per a e b durante la creazione dell'oggetto (Aaa.new(value_for_a, value_for_b)). E definisce to_a per restituire [a,b].

È inoltre possibile utilizzare Struct.new con un blocco per definire metodi aggiuntivi, in modo da avere tutta la potenza di una classe "normale":

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

Questo sembra buono ma ho bisogno di questa funzionalità per gli oggetti, comunque buona risposta non sapevo su Structures – dfens

+1

@dfens: Quelli sono oggetti. 'Struct.new' è solo un metodo factory per le classi. Si otterrebbe lo stesso identico comportamento se si definisse 'Aaa' usando la parola chiave' class' e poi definito '==' ecc. – sepp2k

0

metodo Extra a che fare con il confronto oggetti in Ruby è costituito nell'uso di hash. Per motivi di prestazioni, quando la classe sono enormi, il migliore è quello di utilizzare hash per confrontare rubino oggetti come così:

classe AAA attr_accessor: una,: b

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

def hash (target) @ a.hash == target.a.hash & & @ b.hash == target.b.hash fine fine

A = new Aaa ('qualunque', 'ogni volta') B = new Aaa ('comunque', 'chi') A.hash (B)

1

possiamo facilmente generalizzare a qualsiasi numero di istanze e rilasciare la necessità di getter per le variabili di istanza:

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 

Cambio z a:

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

poi: