What is a guaranteed way to compare two objects by their identity in Ruby? Given two variables, I want to return true if the variables point to the exact same object in memory.
For most Ruby objects, the equal?
method compares by identity:
f = g = Object.new
p f.equal? g # => true
However, this doesn't work for all objects. For example:
class F
def ==(obj) false end
def ===(obj) false end
def eql?(obj) false end
def equal?(obj) false end
def object_id; self end
end
f = g = F.new
p f == g # => false
p f === g # => false
p f.eql? g # => false
p f.equal? g # => false
p f.object_id == g.object_id # => false
What is a foolproof/guaranteed way of comparing two objects by identity which can't be defeated?
This is a purely intellectual question. The answer to any question that begins with "why" will probably be "Because I am curious."
The == operator, also known as equality or double equal, will return true if both objects are equal and false if they are not. str1 = “This is string”
For every object, Ruby offers a method called object_id. You guessed it, this represents a random id for the specific object. This value is a reference of the address in memory where the object is store. Every object has a unique object id that will not change throughout the life of this object.
Whereas the equals() method compares two objects. Objects are equal when they have the same state (usually comparing variables). Objects are identical when they share the class identity. For example, the expression obj1==obj2 tests the identity, not equality.
You could grab an unbound version of Object#object_id
, bind it to the object in question, and see what it says. Given your F
class with one addition:
class F
# ...
def inspect; 'pancakes!' end # Just so we can tell what we have later.
end
Then:
>> f = F.new
>> f.object_id
=> pancakes!
>> unbound_object_id = Object.instance_method(:object_id)
>> unbound_object_id.bind(f).call
=> 2153000340
>> ObjectSpace._id2ref(2153000340).inspect
=> "pancakes!"
Of course, if someone opens up Object and replaces object_id
then you're out of luck but this will be the least of your problems if someone does that. If you can grab your unbound_object_id
UnboundMethod before anything else is loaded, then it won't matter if someone changes Object#object_id
as your unbound_object_id
will still be the original correct one.
So this round-about hack gives you a reliable object_id
for any object (subject to the caveats above). Now you can grab and compare the object ids to get your reliable comparison.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With