`obj.method_name` vs `class " obj`:真正的区别

74 阅读1分钟

我在StackOverflow上看了一些关于Ruby的self.method_nameclass << self 之间的区别的答案。我对这些答案并不满意。虽然所有的答案都很好地解释了object.method_nameclass << object ,但我觉得没有一个人说出了所寻求的区别。这是对这些答案的补充,说明它们的区别

值得注意的细节

对我来说,object.method_nameclass << 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,FloatInteger

这些类的反应与obj.method_nameclass << 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 的子类不能在其实例上有单子方法也无妨。