Ruby中通过身份比较对象的保证方法

Ruby中通过身份比较对象的保证方法,ruby,compare,Ruby,Compare,在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 e

在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
什么是通过身份比较两个无法击败的对象的万无一失/有保证的方法


这是一个纯粹的智力问题。任何以“为什么”开头的问题的答案都可能是“因为我很好奇。”

您可以获取的未绑定版本,将其绑定到所讨论的对象,然后查看它所说的内容。如果您的
F
课程增加了一项内容:

class F
  # ...
  def inspect; 'pancakes!' end # Just so we can tell what we have later.
end
然后:

当然,如果有人打开对象并替换
Object\u id
,那么您就不走运了,但如果有人这样做,这将是您的最小问题。如果您可以在加载任何其他内容之前获取您的
unbound\u object\u id
,那么如果有人更改
object\u id
,则无所谓,因为您的
unbound\u object\u id
仍然是原始的正确id

因此,这轮黑客攻击为任何对象提供了可靠的
object\u id
(根据上述警告)。现在,您可以抓取并比较对象ID,以获得可靠的比较。

mu的答案太短了,这很好,但还有另一种方法可以使用哈希类的特殊功能来实现:

def compare_by_identity(x, y)
  h = {}.compare_by_identity
  h[x] = 1
  h[y] = 2
  h.keys.size == 1
end
Ruby 1.9.2中添加了
compare\u by_identity
功能,因此此功能在早期版本中无法使用。我认为mu太短了,我的答案更好。

使用
BasicObject#equal?
。根据:

与==,相等?方法不应被子类重写:它用于确定对象标识(即,a.equal?(b)如果a是与b相同的对象)


需要更有力的保证吗?如果AIK接收不到它,
BaseObject\object\u id
ObjectSpace.\u id2ref
Hash\u-by\u-identity
也可以被覆盖或修改(至少这是我个人的信念)。

计算机科学和数学中的单词是什么?有一个词来形容它。我想说“恶魔”,但不那么邪恶。我认为这个词是“错误的”。就像在,这不是你应该做的事情。我想用一个以“F”开头的词。。。除非你想写一个C扩展,否则没有任何保证,你应该有礼貌,但没有什么能阻止任何人成为反社会的反社会者。你可以通过
object\u id
不是整数这一事实来判断出有什么不对劲。@Andrew:
def object\u id;兰特(10000)结束
。当面对像
F
这样的病态病例时,你如何依靠“看物体是否等于自身”?真正的潜在问题是,我们不知道如何询问Ruby两个对象是否相等,我们只能询问对象是否相等;如果我们不能信任对象的行为,那么我们该怎么办?太好了,它可以工作!我只想贡献一个函数,它使用这种技术通过标识比较两个变量:
def compare_by_identity(x,y);id=Object.instance\u方法:Object\u id;id.bind(x).call==id.bind(y).call;结束
如果您的态度非常恶劣,您可以提供自己的
def equal?(其他)假结束
实现。
def compare_by_identity(x, y)
  h = {}.compare_by_identity
  h[x] = 1
  h[y] = 2
  h.keys.size == 1
end