Ruby中的"=="是否总是值相等?

6

如果有重复的话我很抱歉(我没有发现)

这只是为了确认 Ruby 的运算符 == 总是执行相等比较。即:

a == b

与Java不同,Ruby将比较a的值和b的值,而不是它们是否指向内存中的相同对象(对于后者,在Ruby中,应使用a.object_id == b.object_id)。

因此,在Ruby中可以安全地使用==比较字符串值(而在Java中这样做是不安全的)。

谢谢

编辑:

问题在于任何Ruby对象的默认==行为,它可能会误导Java-C-C++程序员,认为a==b比较的是引用本身,而不是引用内容。

无论如何,您可以查看此代码,使用字符串

one="hello"
two="he"
two << "llo"

if one == two
  puts "surprise: comparing values, not like in Java"
end

if not one.object_id == two.object_id
  puts "obvious: do this to compare references"
end

编辑2。

在Ruby中,比较操作符

a == b

检查a和b的值

但是,这个赋值语句

a = b

不会复制数值,而是使a和b指向同一个对象!

继续上一个代码示例:

puts one.object_id
puts two.object_id

puts " and now "

one = two

puts one.object_id
puts two.object_id

1
Yes.https://dev59.com/KHI-5IYBdhLWcg3wta_w - nneonneo
1
引用的链接不是此问题的副本... - Brad Werth
是的,我意识到的第一件事是,在Ruby中,运算符==和函数equals的顺序与C语言等语言中所期望的相反。 - EliuX
3个回答

3
在Ruby中,==可以被重载,因此它可以做任何你要比较的类的设计者想让它做的事情。在这方面,它非常类似于Java的equals()方法。
约定是==进行值比较,大多数类都遵循这个约定,包括String。所以你是对的,使用==比较字符串将会得到预期的结果。
约定是equal?进行引用比较,因此你的测试a.object_id == b.object_id也可以写成a.equal?(b)。(equal?方法可能被定义为执行一些非标准操作,但是同样,object_id也可以!)
(旁注:当你发现自己在Ruby中比较字符串时,你通常应该使用符号而不是字符串。)

1

来自http://www.skorks.com/2009/09/ruby-equality-and-object-comparison/

代码:

class MyObject
end
object1 = MyObject.new
object2 = object1
object3 = MyObject.new

puts "Object 1 is == to object 2: #{object1 == object2}"
puts "Object 1 is eql? to object 2: #{object1.eql? object2}"
puts "Object 1 is equal? to object 2: #{object1.equal? object2}"
puts "Object 1 is == to object 3: #{object1 == object3}"
puts "Object 1 is eql? to object 3: #{object1.eql? object3}"
puts "Object 1 is equal? to object 3: #{object1.equal? object3}"

输出:

Object 1 is == to object 2: true
Object 1 is eql? to object 2: true
Object 1 is equal? to object 2: true
Object 1 is == to object 3: false
Object 1 is eql? to object 3: false
Object 1 is equal? to object 3: false

编辑 - 附加输出:

irb(main):001:0> class MyObject
irb(main):002:1> end
=> nil
irb(main):003:0> object1 = MyObject.new
=> #<MyObject:0x281bc08>
irb(main):006:0> object1.respond_to?( '=='.to_sym )
=> true
irb(main):007:0> object1.respond_to?( 'eql?'.to_sym )
=> true
irb(main):013:0> MyObject.superclass
=> Object

1
这是误导性的,因为MyObject没有正确定义任何这些方法。 - Thomas
1
“正确地”指的是“按照惯例”,即:equal?表示引用相等,eql?表示值相等,==表示类型转换后的值相等。上述内容摘自文章(http://www.skorks.com/2009/09/ruby-equality-and-object-comparison/),该文章很好地解释了这一点,但仅凭此代码无法回答实际问题所在的上下文。 - Thomas
1
我不同意...除非被覆盖,否则每个对象都将按照这种方式工作 - 代码是自说明的,并且可以独立存在。 - Brad Werth
2
我相信原始问题是关于所有类的,字符串只是其中一个例子。无论如何,所有方法都会正常执行,直到被覆盖 - 这是不言而喻的... - Brad Werth
我认为你的例子没有阐明重点。请参考我问题中关于字符串的例子。 - cibercitizen1
显示剩余2条评论

0
根据《Ruby编程语言》(Flanagan&Matsumoto),第4.6.7页,第106页

==是等号运算符。它根据左操作数对“相等”的定义确定两个值是否相等。

在第3.8.3页上:

每个对象都有一个对象标识符,即Fixnum,您可以使用object_id方法获取该标识符。此方法返回的值对于对象的生命周期是恒定且唯一的。

因此,这与Java相反(对我来说很惊讶)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接