我是ruby元编程的新手,我看到人们在不同的地方对代码进行元编程,例如class Object
,class Module
,module Kernel
和“无”(即,在课堂外) / module definition block。
例如:我正在创建一个c_attr_accessor
方法来访问类变量,我不确定在哪里放置代码,因为它适用于任何一种情况。
如何确定哪个地方更适合投放新的全球代码?
答案 0 :(得分:3)
这些例子中的每一个都属于不同的情况。
如果您正在编写适用于所有对象的方法,则打开Object
类,以便所有对象都可以访问它。如果您正在编写适用于所有模块的方法,则打开Module
。无论何时打开一个类来添加方法,这些方法都应该适用于类的所有实例,而不是其他任何。
扩展Kernel
模块是不同的:人们这样做是为了添加应该可用于每个范围的方法,但实际上并不是通过将它们设为私有而在对象上显式调用的方法。
当您在任何class
或module
语句之外时,您处于main
对象的范围内,并且您定义的方法默认为{{1}的私有方法}。这适用于小型或简单的程序,但最终您希望使用适当的模块作为命名空间来组织方法。
作为关于这个主题的最后一点,您总是需要确保您真正希望添加到内置类和模块的方法可用于应用程序中的所有内容,包括外部包含因为他们都共享内置插件。
现在应用它来回答你的问题。因为您要定义一个为类变量创建访问器的方法,所以应该将它放在类Object
中,因为它适用于所有类而不是其他任何类。最后,您可能只会在类定义中使用它(在Class
语句中),因此我们应该将其设为私有:
class
如果你并不是真的需要每个类(可能只是几个),那么创建一个“mixin模块”来扩展需要此功能的每个类:
class Class
private
def c_attr_accessor(name)
# ...
end
end
class User
c_attr_accessor :class_variable_name
# ...
end
请注意,您使用module ClassVariableAccessor
private
def c_attr_accessor(name)
# ...
end
end
class User
extend ClassVariableAccessor
c_attr_accessor :class_variable_name
# ...
end
仅将Object#extend
添加到对象c_attr_accessor
(请记住,类是对象;如果您不熟悉Ruby元编程,您会听到很多内容)
还有另一种实现最后一个示例的方法,它通过在包含模块时调用的User
“钩子方法”显式扩展其基类,并将基类传递给Module#included(base_class)
:
base_class
我推荐这最后一个解决方案,因为它是最常用的,并且使用了一个不需要更新的简单界面。我希望这不是太多!
答案 1 :(得分:1)
您是否尝试查找定义普通属性访问器的位置?我要么在相同的类/模块中定义它,要么创建我自己的所有新方法所用的模块。