Guaranteed way to compare objects by identity in Ruby
Use BasicObject#equal?
. According to Ruby documentation:
Unlike ==, the equal? method should never be overridden by subclasses: it is used to determine object identity (that is, a.equal?(b) iff a is the same object as b).
Need stronger guarantee? AFAIK can't receive it, BaseObject#object_id
, ObjectSpace._id2ref
, Hash#compare_by_identity
can be overriden or monkey patched too (at least this is my personal belief).
The answer by mu is too short is great, but there is another way you can do it using a special feature of the Hash class:
def compare_by_identity(x, y)
h = {}.compare_by_identity
h[x] = 1
h[y] = 2
h.keys.size == 1
end
The compare_by_identity
feature was added in Ruby 1.9.2, so this function won't work in earlier versions. I think mu is too short's answer is better.
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.