在 ruby 中一切皆对象 (Object),既然是对象,则可以用来对等比较。
Object.methods.grep /\=\=/ #=> [:==, :===]
我们可以看到确实存在 ==
的方法可以用来对等比较所有对象。
于是,我们对下列对象自身作对比:
# Module
Object == Object #=> true
# Class
String == String #=> true
# Proc
p = -> {x + y + z}
p == p #=> true
# Object
"A" == String.new("A") #=> true
1 == Integer(1) #=> true
nil == nil #=> true
这看起来自身对比的结果都是一样的,皆为true
,
但当我们对比到method
时,情况发生了变化:
require 'date'
method_one = Object.instance_method(:method).bind(Date.today).call(:year) #=> #<Method: Date#year>
method_two = Date.today.method(:year) #=> #<Method: Date#year>
method_one.receiver == method_two.receiver # true
method_one == method_two # false
# method_two == method_two # false # 经测试,结果为 true,此处写错
# or
Date.today.method(:year) == Date.today.method(:year) # false
我们发现,同一个method
在自身对比时并不相等,有意思了。怎解? [手动滑稽]
补充
我发现 Method
的 ==
方法被重写了,它和普通的 Object
不一样,其 C 代码如下:
static VALUE
method_eq(VALUE method, VALUE other)
{
struct METHOD *m1, *m2;
VALUE klass1, klass2;
if (!rb_obj_is_method(other))
return Qfalse;
if (CLASS_OF(method) != CLASS_OF(other))
return Qfalse;
Check_TypedStruct(method, &method_data_type);
m1 = (struct METHOD *)DATA_PTR(method);
m2 = (struct METHOD *)DATA_PTR(other);
klass1 = method_entry_defined_class(m1->me);
klass2 = method_entry_defined_class(m2->me);
if (!rb_method_entry_eq(m1->me, m2->me) ||
klass1 != klass2 ||
m1->klass != m2->klass ||
m1->recv != m2->recv) {
return Qfalse;
}
return Qtrue;
}
所以,method
的判断机制就包含在代码中了,可惜,看不太懂 - -
如果有人能解读一下就好