equal?、eql?、=== 和 == 之间有什么区别? [英] What's the difference between equal?, eql?, ===, and ==?
问题描述
我试图了解这四种方法之间的区别.我知道默认情况下 ==
调用方法 equal?
当两个操作数引用完全相同的对象时返回 true.
====
默认也调用 ==
调用 equal?
... 好吧,如果这三个方法都不是被覆盖,那么我猜====
, ==
和 equal?
做的完全一样吗?
现在来eql?
.这是做什么的(默认情况下)?它是否调用操作数的哈希/id?
为什么 Ruby 有这么多等号?他们应该在语义上有所不同吗?
我要大量引用 对象文档 在这里,因为我认为它有一些很好的解释.我鼓励你阅读它,以及这些方法的文档,因为它们在其他类中被覆盖,比如 字符串.
旁注:如果您想在不同的对象上亲自尝试这些,请使用以下方法:
class 对象def all_equals(o)ops = [:==, :===, :eql?, :equal?]哈希[ops.map(&:to_s).zip(ops.map {|s| send(s, o) })]结尾结尾a".all_equals a"# =>{=="=>真,==="=>真,eql?"=>真,等于?"=>假}
==
— 通用的相等"
<块引用>在对象级别,仅当 obj
和 other
是同一个对象时,==
才返回 true.通常,此方法在后代类中被覆盖以提供特定于类的含义.
这是最常见的比较,因此也是您(作为类的作者)决定两个对象是否相等"的最基本的地方.与否.
====
— 大小写相等
<块引用>对于 Object 类,实际上与调用 #==
相同,但通常由后代覆盖以在 case 语句中提供有意义的语义.
这非常有用.具有有趣的 ===
实现的事物示例:
- 范围
- 正则表达式
- Proc(在 Ruby 1.9 中)
因此您可以执行以下操作:
case some_object当/a 正则表达式/# 正则匹配当 2..4# some_object 在 2..4 范围内当 lambda {|x|some_crazy_custom_predicate }# lambda 返回真结尾
请参阅我在此处的回答case
+Regex
如何让代码更简洁的一个很好的例子.当然,通过提供您自己的 ===
实现,您可以获得自定义的 case
语义.
eql?
— Hash
等式
<块引用>如果 obj
和 other
引用相同的哈希键,则 eql?
方法返回 true.Hash
使用它来测试成员是否相等.对于 Object
类的对象,eql?
是 ==
的同义词. 子类通常通过别名 eql?
到他们重写的 ==
方法,但也有例外.Numeric
类型,例如跨==
进行类型转换,但不跨eql?
,所以:
1 == 1.0 #=>真的1.eql?1.0 #=>错误的
所以你可以自由地覆盖它以供你自己使用,或者你可以覆盖 ==
并使用 alias :eql?:==
所以这两种方法的行为方式相同.
equal?
— 身份比较
<块引用>与 ==
不同,equal?
方法不应该被子类覆盖:它用于确定对象身份(即 a.equal?(b)
当 a
与 b
是同一个对象.
这是有效的指针比较.
I am trying to understand the difference between these four methods. I know by default that ==
calls the method equal?
which returns true when both operands refer to exactly the same object.
===
by default also calls ==
which calls equal?
... okay, so if all these three methods are not overridden, then I guess
===
, ==
and equal?
do exactly the same thing?
Now comes eql?
. What does this do (by default)? Does it make a call to the operand's hash/id?
Why does Ruby have so many equality signs? Are they supposed to differ in semantics?
I'm going to heavily quote the Object documentation here, because I think it has some great explanations. I encourage you to read it, and also the documentation for these methods as they're overridden in other classes, like String.
Side note: if you want to try these out for yourself on different objects, use something like this:
class Object
def all_equals(o)
ops = [:==, :===, :eql?, :equal?]
Hash[ops.map(&:to_s).zip(ops.map {|s| send(s, o) })]
end
end
"a".all_equals "a" # => {"=="=>true, "==="=>true, "eql?"=>true, "equal?"=>false}
==
— generic "equality"
At the Object level,
==
returns true only ifobj
andother
are the same object. Typically, this method is overridden in descendant classes to provide class-specific meaning.
This is the most common comparison, and thus the most fundamental place where you (as the author of a class) get to decide if two objects are "equal" or not.
===
— case equality
For class Object, effectively the same as calling
#==
, but typically overridden by descendants to provide meaningful semantics in case statements.
This is incredibly useful. Examples of things which have interesting ===
implementations:
- Range
- Regex
- Proc (in Ruby 1.9)
So you can do things like:
case some_object
when /a regex/
# The regex matches
when 2..4
# some_object is in the range 2..4
when lambda {|x| some_crazy_custom_predicate }
# the lambda returned true
end
See my answer here for a neat example of how case
+Regex
can make code a lot cleaner. And of course, by providing your own ===
implementation, you can get custom case
semantics.
eql?
— Hash
equality
The
eql?
method returns true ifobj
andother
refer to the same hash key. This is used byHash
to test members for equality. For objects of classObject
,eql?
is synonymous with==
. Subclasses normally continue this tradition by aliasingeql?
to their overridden==
method, but there are exceptions.Numeric
types, for example, perform type conversion across==
, but not acrosseql?
, so:1 == 1.0 #=> true 1.eql? 1.0 #=> false
So you're free to override this for your own uses, or you can override ==
and use alias :eql? :==
so the two methods behave the same way.
equal?
— identity comparison
Unlike
==
, theequal?
method should never be overridden by subclasses: it is used to determine object identity (that is,a.equal?(b)
iffa
is the same object asb
).
This is effectively pointer comparison.
这篇关于equal?、eql?、=== 和 == 之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!