在 Ruby 中按身份比较对象的有保证的方法
在 Ruby 中通过身份比较两个对象的有保证的方法是什么?给定两个变量,如果变量指向内存中完全相同的对象,我想返回 true。
对于大多数 Ruby 对象,equal?
方法按同一性进行比较:
f = g = Object.new
p f.equal? g # => true
但是,这并不适用于所有对象。例如:
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 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."
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以获取
Object#object_id
,将其绑定到有问题的对象,然后看看它说什么。给定您的F
类并添加一个:那么:
当然,如果有人打开 Object 并替换
object_id
那么您就不走运了,但这将是您的最少的如果有人这样做就会出现问题。如果您可以在执行其他操作之前获取您的unbound_object_id
UnboundMethod加载,那么即使有人更改Object#object_id
也没关系,因为您的unbound_object_id
仍然是原始的正确 ID。因此,这个迂回的黑客行为为您提供了任何对象的可靠
object_id
(受上述警告的约束)。现在您可以抓取并比较对象 ID,以获得可靠的比较。You could grab an unbound version of
Object#object_id
, bind it to the object in question, and see what it says. Given yourF
class with one addition:Then:
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 yourunbound_object_id
UnboundMethod before anything else is loaded, then it won't matter if someone changesObject#object_id
as yourunbound_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.使用
BasicObject#equal?
。根据 Ruby 文档:需要更有力的保证? AFAIK 无法接收它,
BaseObject#object_id
、ObjectSpace._id2ref
、Hash#compare_by_identity
也可以被覆盖或猴子修补(至少这个是我个人的信念)。Use
BasicObject#equal?
. According to Ruby documentation: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).mu 太短了 的答案很好,但是还有另一种方法可以使用 Hash 类的特殊功能来做到这一点:
Ruby 1.9 中添加了
compare_by_identity
功能.2,所以这个功能在早期版本中不起作用。我认为mu太短的答案更好。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:
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.