方法调用通常可以省略接收器和参数的括号:
def foo; "foo" end
foo # => "foo"
在上述情况下,
foo
在方法调用和引用潜在局部变量之间存在歧义。如果不存在后者,则它将被解释为方法调用。但是,当方法名原则上可以是常量名时(即以大写字母开头,且仅由字母组成),似乎需要消除歧义。
def Foo; "Foo" end
Foo # => NameError: uninitialized constant Foo
Foo() # => "Foo"
self.Foo # => "Foo"
为什么会这样呢?即使没有同名的常量,为什么方法调用还需要明确地与常量引用区分开来?
freeze
来冻结类。但实际上,区别在于:通过猴子补丁修改方法而导致的变化是可以预期的。而引入常量所导致的变化则不是。请注意,这不仅仅涉及到定义Foo::Bar
。还包括在Foo
的任何超类中定义名为Bar
的常量,或者在任何被Foo
包含的模块中定义名为Bar
的常量,或者在任何被Foo
或其超类之一包含的模块中定义名为Bar
的常量,或者在任何被Foo
或其超类之一包含的模块所包含的任何模块中定义名为Bar
的常量等等。常量是通过继承进行查找的,它们可能会出现在很远的地方! - Jörg W Mittag