我正在尝试创建一个将包含在许多不同类中的模块。它需要记录调用者到类文件的路径 所以我可以在后面的代码中引用该路径。此代码尝试向调用类添加方法,但失败,因为它只返回@@ x的当前值。
# /home/eric/FindMe.rb
class FindMe
include GladeGUI
end
# /home/eric/GladeGUI.rb
module GladeGUI
def self.included(obj)
@@x, = caller[0].partition(":") # this works @@x = "/home/eric/FindMe.rb"
obj.class_eval do
def my_class_file_path
return ????? # I want to return "/home/eric/FindMe.rb"
end
end
end
end
GladeGUI模块将“包含”在许多不同的类中,因此我不能只将代码添加到调用类中。我需要一种方法将@@ x编译成一个常量值,因此存储在类中的方法如下所示:
def my_class_file_path
return "/home/eric/FindMe.rb"
end
如何在代码中将变量转换为常量?
感谢。
答案 0 :(得分:2)
看起来你实际上并不需要它是一个“常量” - 你只需要一些方法让方法始终返回正确的值而不允许其他代码出现并更改值(使用当前的@@x
解决方案,有人可以修改@@x
并且它会破坏)
解决方案是将数据存储在局部变量而不是类或实例变量中,然后通过闭包访问该局部变量。
没有其他代码可以“查看”局部变量,因此无法更改。
但问题变成了当你在class_eval中使用def时,调用者的范围没有被捕获,因此代码无法看到你的局部变量。您可以使用define_method
代替
这是一个例子
# /home/eric/GladeGUI.rb
module GladeGUI
def self.included(obj)
caller_file_path = caller[0].split(":").first
obj.class_eval do
define_method :my_class_file_path do
return caller_file_path
end
end
end
end
# /home/eric/FindMe.rb
class FindMe
include GladeGUI
end
puts FindMe.new.my_class_file_path # prints the correct path
但是 - 如果您希望my_class_file_path
成为类方法而非实例方法,请使用define_singleton_method
代替:
module GladeGUI
def self.included(obj)
caller_file_path = caller[0].split(":").first
obj.class_eval do
define_singleton_method :my_class_file_path do
return caller_file_path
end
end
end
end
...
puts FindMe.my_class_file_path
有趣的旁注:这是你在javascript中假冒“私人变量”的方法: - )