Ruby 中的模块方法
Module methods in Ruby
这是我的代码:
module Star
def Star.line
puts '*' * 20
end
end
module Dollar
def Star.line
puts '$' * 20
end
end
module At
def line
puts '@' * 20
end
end
include At
Dollar::line # => "@@@@@@@@@@@@@@@@@@@@"
Star::line # => "$$$$$$$$$$$$$$$$$$$$"
Dollar::line # => "@@@@@@@@@@@@@@@@@@@@"
line # => "@@@@@@@@@@@@@@@@@@@@"
谁能解释一下我是如何得到这个结果的?我不明白这里的方法查找流程。
我是这样看的:
Dollar::line
此模块中没有定义此类方法,因此调用 At::line
因为您包含了此模块。
Star::line
它使用来自 Dollar
模块的最后定义(它遵循原始 Star
定义,因此被覆盖)。
Dollar::line
第三次调用与第一次相同。
line
最后一个是 At::line
因为你做了一个包含。
是
module Dollar
def Star.line
是故意的还是打字错误?
貌似Dollar.line
没有定义,改用At
中的方法line
首先您需要了解 Ruby 查找常量与查找方法有点相似。它首先在当前 词法范围 中查找常量。如果它在那里没有找到常量,它会上升一级并在那里寻找,依此类推。如果它在其他地方找不到常量,它最终会搜索顶层,这就是为什么您可以从代码中的任何位置访问 Kernel
等模块。
module Star
end
Star.object_id # 20
module Dollar
Star.object_id # 20. No Star in current scope, so gets the top-level star
end
module At
module Star
end
Star.object_id # 10. There is now a Star in this scope, so we don't get the top-level one
end
接下来要了解的是 Ruby 中顶层定义的方法是 Object
的 实例 方法。由于 Ruby 中的所有内容都是 Object
的实例,因此始终可以调用此类方法。
最后,考虑一下 include
的作用:它从模块中获取实例方法,并使它们成为当前作用域中的实例方法。因此,如果您 include
位于顶层的内容,所有这些方法都会添加到 Object
!
所以你的代码基本上等同于:
module Star
def self.line
puts '*' * 20
end
# this overwrites the previous definition
def self.line
puts '$' * 20
end
end
# because of the way constants are looked up, the def ends up in Star
module Dollar
end
module At
def line
puts '@' * 20
end
end
# the include does this, so now every object (including Dollar) can call line
def line
puts '@' * 20
end
# except Star already has its own line method, so the one from Object won't be called for it
Star.line # "$$$$$$$$$$$$$$$$$$$$"
这是我的代码:
module Star
def Star.line
puts '*' * 20
end
end
module Dollar
def Star.line
puts '$' * 20
end
end
module At
def line
puts '@' * 20
end
end
include At
Dollar::line # => "@@@@@@@@@@@@@@@@@@@@"
Star::line # => "$$$$$$$$$$$$$$$$$$$$"
Dollar::line # => "@@@@@@@@@@@@@@@@@@@@"
line # => "@@@@@@@@@@@@@@@@@@@@"
谁能解释一下我是如何得到这个结果的?我不明白这里的方法查找流程。
我是这样看的:
Dollar::line
此模块中没有定义此类方法,因此调用 At::line
因为您包含了此模块。
Star::line
它使用来自 Dollar
模块的最后定义(它遵循原始 Star
定义,因此被覆盖)。
Dollar::line
第三次调用与第一次相同。
line
最后一个是 At::line
因为你做了一个包含。
是
module Dollar
def Star.line
是故意的还是打字错误?
貌似Dollar.line
没有定义,改用At
中的方法line
首先您需要了解 Ruby 查找常量与查找方法有点相似。它首先在当前 词法范围 中查找常量。如果它在那里没有找到常量,它会上升一级并在那里寻找,依此类推。如果它在其他地方找不到常量,它最终会搜索顶层,这就是为什么您可以从代码中的任何位置访问 Kernel
等模块。
module Star
end
Star.object_id # 20
module Dollar
Star.object_id # 20. No Star in current scope, so gets the top-level star
end
module At
module Star
end
Star.object_id # 10. There is now a Star in this scope, so we don't get the top-level one
end
接下来要了解的是 Ruby 中顶层定义的方法是 Object
的 实例 方法。由于 Ruby 中的所有内容都是 Object
的实例,因此始终可以调用此类方法。
最后,考虑一下 include
的作用:它从模块中获取实例方法,并使它们成为当前作用域中的实例方法。因此,如果您 include
位于顶层的内容,所有这些方法都会添加到 Object
!
所以你的代码基本上等同于:
module Star
def self.line
puts '*' * 20
end
# this overwrites the previous definition
def self.line
puts '$' * 20
end
end
# because of the way constants are looked up, the def ends up in Star
module Dollar
end
module At
def line
puts '@' * 20
end
end
# the include does this, so now every object (including Dollar) can call line
def line
puts '@' * 20
end
# except Star already has its own line method, so the one from Object won't be called for it
Star.line # "$$$$$$$$$$$$$$$$$$$$"