为什么 Ruby 找不到调用者的 class 中定义的常量?
Why doesn't Ruby find constants defined in the caller's class?
考虑以下代码:
class MyClass
def foo_via_method
foo_method
end
def foo_via_constant
FOO_CONSTANT
end
end
class SubClass < MyClass
FOO_CONSTANT = "foo"
def foo_method
FOO_CONSTANT
end
end
这里的两个实例方法表现不同:
sub_class_instance = SubClass.new
### THIS WORKS ###
sub_class_instance.foo_via_method
# => "foo"
### THIS DOESN'T ###
sub_class_instance.foo_via_constant
# NameError: uninitialized constant MyClass::FOO_CONSTANT
引用子类中方法的版本 returns 期望值,但引用子类中常量的版本抛出错误。所以问题是:为什么使用方法的版本有效,而使用常量的版本失败?
这是我在实际生产代码中遇到的一个难题。我在 this blog post.
中详细解释了发生的事情
这里是 TLDR:Ruby 使用比解析方法复杂得多的算法来解析常量。常量查找例程的一个阶段涉及在 superclass 链中查找定义。这个阶段看起来非常像方法查找例程,加深了为什么方法和常量在问题中说明的方式不同的谜团。
解释是两个 superclass 链例程的不同之处在于它们 开始 ,即哪个 class 是链的根。
方法查找从 self
的 class 开始,其中 self
是原始方法调用的接收者。在示例中,sub_class_instance
是接收方,SubClass
是查找开始的位置。 SubClass
实现了 foo_method
,所以一切都很好。
对于常量,Ruby 不引用接收者,因为常量调用与接收者无关。相反,常量 superclass 查找从 class 开始,它在常量调用发生的词法范围内打开。在这个例子中,打开的 class 是 MyClass
,所以这就是 Ruby 开始寻找常量的地方——但从未找到它。
考虑以下代码:
class MyClass
def foo_via_method
foo_method
end
def foo_via_constant
FOO_CONSTANT
end
end
class SubClass < MyClass
FOO_CONSTANT = "foo"
def foo_method
FOO_CONSTANT
end
end
这里的两个实例方法表现不同:
sub_class_instance = SubClass.new
### THIS WORKS ###
sub_class_instance.foo_via_method
# => "foo"
### THIS DOESN'T ###
sub_class_instance.foo_via_constant
# NameError: uninitialized constant MyClass::FOO_CONSTANT
引用子类中方法的版本 returns 期望值,但引用子类中常量的版本抛出错误。所以问题是:为什么使用方法的版本有效,而使用常量的版本失败?
这是我在实际生产代码中遇到的一个难题。我在 this blog post.
中详细解释了发生的事情这里是 TLDR:Ruby 使用比解析方法复杂得多的算法来解析常量。常量查找例程的一个阶段涉及在 superclass 链中查找定义。这个阶段看起来非常像方法查找例程,加深了为什么方法和常量在问题中说明的方式不同的谜团。
解释是两个 superclass 链例程的不同之处在于它们 开始 ,即哪个 class 是链的根。
方法查找从 self
的 class 开始,其中 self
是原始方法调用的接收者。在示例中,sub_class_instance
是接收方,SubClass
是查找开始的位置。 SubClass
实现了 foo_method
,所以一切都很好。
对于常量,Ruby 不引用接收者,因为常量调用与接收者无关。相反,常量 superclass 查找从 class 开始,它在常量调用发生的词法范围内打开。在这个例子中,打开的 class 是 MyClass
,所以这就是 Ruby 开始寻找常量的地方——但从未找到它。