tags:

views:

90

answers:

3

In Java I can do:

public boolean equals(Object other) {
    return this.aPrivateVariable == ((MyClass)other).aPrivateVariable;
}

This allows me to define equality without breaking the encapsulation of my class. How can I do the same in Ruby?

Thanks.

+3  A: 

In ruby instance variables as well as private methods are accessible only to the object itself, not to any other object no matter their class. Protected methods are available to the object itself and other objects of the same class.

So to do what you want you can define a protected getter-method for your variable.

Edit: An example:

class Foo
  protected
  attr_accessor :my_variable # Allows other objects of same class
                             # to get and set the variable. If you
                             # only want to allow getting, change
                             # "accessor" to "reader"

  public
  def ==(other)
    self.my_variable == other.my_variable
  end
end
sepp2k
I will check but that looks like the answer to me :)
soulnafein
A: 

Just do the comparison without the cast which is not necessary in Ruby.

class C1
  attr_accessor :property

  def == other
    property == other.property
  end
end

class C2
  attr_accessor :property

  def == other
    property == other.property
  end
end

c1 = C1.new
c1.property = :foo

c2 = C2.new
c2.property = :bar

p c1 == c2 # => false

c1.property = :bar
p c1 == c2 # => true

Edit: Changed equals? to ==.

I'm pretty sure he doesn't want the variable to be readable or settale from outside (not counting reflection which always works anyway), which is why he called his variable "aPrivateVariable". Also: don't override `equals?`, it will break things. Override `==`.
sepp2k
You are right about equals? vs. ==. The accessor is just for demonstration. The OP can easily change that part.
Exactly I don't want the variable accessible from outside.
soulnafein
A: 

As others have pointed out, you need to redefine #== in your class. One gotcha, though, is hash tables. If you want two different instances of your class with o1 == o2 #=> true to hash to the same value in a hash table, then you need to redefine #hash and #eql? so the hash table knows they represent the same value.

class Foo
  def initialize(x,y,z)
    @x,@y,@z = x,y,z
  end
  def ==(other)
    @y == other.instance_eval { @y }
  end
end

o1 = Foo.new(0, :frog, 2)
o2 = Foo.new(1, :frog, 3)

o1 == o2 #=> true

h1 = Hash.new
h1[o1] = :jump
h1[o2] #=> nil

class Foo
  def hash
    @y.hash
  end
  def eql?(other)
    self == other
  end
end

h2 = Hash.new
h2[o1] = :jump_again
h2[o2] #=> :jump_again
rampion