まず、Ruby がメソッドと同じように定数を検索することを理解する必要があります。現在のレキシカルスコープで定数を探すことから始めます。そこに定数が見つからない場合は、1 レベル上に移動してそこを探します。定数がどこにも見つからない場合は、最終的に最上位を検索します。これが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 # "$$$$$$$$$$$$$$$$$$$$"