我有一個里面有一個類的模塊,但是我發現里面的類在不指定模塊路徑的情況下無法訪問封閉模塊中的任何方法。
另一種看待它的方式是 module_function 似乎沒有帶入類。
例子:
module MyMod
def meaning
42
end
class Foo
def initialize
puts "New Foo"
puts "I can call #{MyMod.meaning} from here"
puts "But I can't get to #{meaning} from here"
end
end
def go
puts "I can get to #{meaning} from here"
bar = Foo.new
end
module_function :go, :meaning
go
end
如果你運行這個,你會在“但我不能......”行上得到一個錯誤:
undefined local variable or method `meaning'
但是,如果您洗掉整個檔案周圍的 MyMod 位,則訪問外部方法沒有問題。
有沒有一種簡單的方法可以讓這些訪問而無需提供完整路徑?
(我挑剔不包括完整路徑的原因之一是因為我正在使用http://redshift.sourceforge.net/script/來創建我可以實體化的 ruby?? 腳本 - 而它們沒有像“MyMod”這樣清晰而簡單的名稱,我可以將其添加到路徑中,實際上我必須傳遞范圍,即使它只是類的封閉范圍)
uj5u.com熱心網友回復:
我有一個里面有一個類的模塊,
不,你沒有。您有一個包含類定義的模塊定義,但這不會使類成為嵌套類。Ruby 沒有嵌套類。
Ruby 不是Beta、Scala或Newspeak,Ruby 中沒有嵌套類。
嵌套的模塊或類定義另一模塊或類定義內也不會創建兩個類/模塊之間的嵌套關系。它只生成參考外部類/模塊命名空間的類/模塊部分的常量。
換句話說,兩者之間沒有區別
module Foo
class Bar
end
end
和
class Quux
end
module Foo
Bar = Quux
end
僅嵌套常量,而不嵌套常量參考的物件。
但是我發現內部的類在不指定模塊路徑的情況下無法訪問封閉模塊中的任何方法。
那正是因為沒有“封閉模塊”。有一個詞法上封閉模塊定義,但是這并沒有產生任何形式的任何之間的關系,Foo類和MyMod模塊。
另一種看待它的方式是 module_function 似乎沒有帶入類。
老實說,我不明白你的意思,一個方法“進入一個類”意味著什么,但Module#module_function不是魔術。它完全按照檔案所說的去做:它采用模塊的實體方法,將其復制為模塊的單例類的實體方法,并生成原始實體方法private。
您可以在 Ruby/Spec 中閱讀它的規范,它相當簡單。此外,Rubinius源代碼,無論是用于引導 Rubinius 內核的基本版本還是完整版本,都具有相當的可讀性。
到最后,Module#module_function真的不比
class Module
def module_function(*meths)
meths.each do |meth|
define_singleton_method(meth, &instance_method(meth).bind(self))
private meth
end
self
end
end
如果你運行這個,你會在“但我不能......”行上得到一個錯誤:
undefined local variable or method `meaning'
原因很簡單:類Foo和它的任何超類都沒有任何同名的方法,所以當然會得到一個例外。
但是,如果您洗掉整個檔案周圍的 MyMod 位,則訪問外部方法沒有問題。
There is no "outer method". Ruby does not have Beta-like nested classes. That is really the fundamental cause of your misunderstanding. You expect Ruby to behave like Beta, but it just doesn't. Ruby takes inspiration from any languages, most notably (in rough order of importance) Smalltalk, Lisp, Perl, and Clu, but Beta is not among them.
This here works for a completely different reason:
def meaning
42
end
class Foo
def initialize
meaning
end
end
Methods that are defined at the top-level are implicitly defined as private instance methods of Object. This is because the default definee at the top-level is ::Object. Since Foo inherits from Object, method lookup will eventually find the meaning method defined in Object.
Is there an easy way to make these accessible without having to give the full path?
Inheritance. For example, Module#append_features, which is called by Module#include, makes the module the superclass of the including class, and thus all instance methods of the module become part of the method lookup ancestry chain.
An aside: if there is no nesting, then what does Module::nesting do? Well, yeah, that is an unfortunately named method. The term "nested class" or "nested module" has a well-defined meaning in OO going all the way back to Beta. But this method is about a completely different kind of nesting:
It refers to the lexical nesting of module definitions, and not to nesting of modules themselves.
For example, these module definitions all define the exact same module, but the definition text has different nesting:
module Foo
module Bar
module Baz
module Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo::Bar::Baz, Foo::Bar, Foo]
end
end
end
end
module Foo
module Bar
module Baz::Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo::Bar, Foo]
end
end
end
module Foo
module Bar::Baz
module Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo::Bar::Baz, Foo]
end
end
end
module Foo::Bar
module Baz
module Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo::Bar::Baz, Foo::Bar]
end
end
end
module Foo
module Bar::Baz::Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo]
end
end
module Foo::Bar::Baz
module Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo::Bar::Baz]
end
end
module Foo::Bar
module Baz::Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo::Bar]
end
end
module Foo::Bar::Baz::Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux]
end
Again, this is purely lexical nesting of the module definition. The module itself is not nested; the module itself is the same in all of these cases. This nesting only affects constant lookup.
Constants are looked up first lexically outwards in enclosing module definitions, then upwards the inheritance chain.
還有另一個可以嵌套事物的實體:塊創建嵌套的詞法范圍,而所有其他詞法范圍(腳本、模塊/類定義和方法定義)不嵌套。換句話說,塊和只有塊才能訪問self其封閉詞法范圍的區域變數(和)。
uj5u.com熱心網友回復:
由于 Ruby 名稱決議和方法查找的作業方式。當您x在任何地方撰寫代碼時,Ruby 會按以下順序:
查找
x區域變數在里面找
x方法self.class在里面找
x方法self.superclass重復步驟3直到
superclass就是nilRuby 將沿著類層次結構向上查找該方法,
x直到它到達BasicObject.呼叫
method_missing它的默認行為是引發您遇到的錯誤。
MyMod僅包含Foo,它不是Foo類層次結構的一部分。這就是找不到方法的原因。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/336762.html
下一篇:有沒有辦法專門回圈多次
