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