
我在StackOverflow上看了一些关于Ruby的self.method_name 和class << self 之间的区别的答案。我对这些答案并不满意。虽然所有的答案都很好地解释了object.method_name 和class << object ,但我觉得没有一个人说出了所寻求的区别。这是对这些答案的补充,说明它们的区别。
值得注意的细节
对我来说,object.method_name 和class << object 之间值得宣传的区别将是这两种符号如何解决常数。让我们通过一个例子。
让我们假设我们有一个这样的程序:
FLIGHT_NUMBER = "QTR1"
aircraft = Object.new
class << aircraft
FLIGHT_NUMBER = "QTR5"
end
在我们的短程序中,我们有两个常量,都被命名为FLIGHT_NUMBER ,但数值不同。注意我们是如何在aircraft's anonymous (singleton) class里面设置最后一个常量的。
有了上面的内容,让我们使用这两种符号来定义单子方法,并调用这些方法:
def aircraft.print_flight_no
puts FLIGHT_NUMBER
end
class << aircraft
def show_flight_no
puts FLIGHT_NUMBER
end
end
aircraft.print_flight_no
aircraft.show_flight_no
这就返回了:
QTR1
QTR5
正如一位Redditor所简明指出的:
当你写
def object.method_name,你是在指定对象的特征类中定义了一个方法,但没有改变默认的 "definee "或该方法主体中的 "cref"。当你写
class << object,你在用对象的特征类更新默认的 "definee "和 "cref",直到类定义结束。- 脆弱的_Pomelo
在互联网的深处有一些关于这个问题的罕见阐述。
我们的常数的可见性受到我们挑选的符号的影响。一般来说,两种符号的明显含义是相似的。如果类方法的范围和分组对你来说是重要的,你就选择一个而不是另一个。
不同的符号,不同的反应
就像你已经知道的,Ruby中的一切(几乎)都是一个对象。除了Numeric 类的子类之外,这些对象可以有单子方法附加在它们身上。Complex,Rational,Float 和Integer 。
这些类的反应与obj.method_name 和class << obj 不同。 这里有一个例子:
class << Complex(1)
def hi
"hey!"
end
end
上面的内容会输出这样的结果:
can't modify frozen object: 1+0i (FrozenError)
这样做:
int = 5
class << int
def hi
"hey!"
end
end
# OR
def int.hi
"hey!"
end
将输出:
can't define singleton (TypeError)
Numeric 类的子类对这两种定义单子方法的方式表现不同。你不应该认为这是一个真正的区别,但是知道Numeric 的子类不能在其实例上有单子方法也无妨。