何时在模块的方法中使用 self
When to use self in module's methods
我的模块定义如下所示:
module RG::Stats
def self.sum(a, args = {})
a.inject(0){ |accum, i| accum + i }
end
end
要使用此方法,我只需要包含此定义的文件即可:
RG::Stats.sum(array)
还有
RG::Stats.method(:sum)
但是,如果我需要知道使用 RG::Stats.instance_methods
的方法列表,我会得到一个空数组。这是因为我使用了self
。如果我省略 self
,那么 RG::Stats.instance_methods
会给出方法列表,但我无法再访问它们。
问题是:如何在模块的方法定义中使用self
?
如果你使用self
,那么你可以直接使用模块方法使用: RG::Stats.sum(array)
如上所述。
如果您不使用 self
在模块中定义方法,那么对于包含模块的 class,该方法将被包含为 instance_method
。
因此,您可以在 RG::Stats
模块中定义 sum
实例方法:
module RG::Stats
def sum(a, args = {})
a.inject(0){ |accum, i| accum + i }
end
end
然后,您可以在 class 中包含 RG::Stats
模块,然后 sum
方法将作为 instance_method
用于 [=38= 的对象]:
class YourClass
include RG::Stats
. . .
. . .
end
并且您可以在 YourClass
的实例上调用 sum
方法:
YourClass.new.sum
要回答您的问题,您可以使用 self
将您的方法定义为模块内的 class 方法,而不使用 self
将方法定义为实例方法,并且它取决于您的需要和用例,当您想要从模块方法中获得什么类型的行为时。
因为def self.sum
没有定义实例方法;您使用了错误的方法 select 它。试试这个:
RG::Stats.methods(false)
# => [:sum]
如果您希望仅在模块的单例 class 中定义方法(其中使用 self
定义的方法存在),请在每个方法定义中使用 self
。如果希望模块的方法同时定义为实例方法和单例方法,则省略self和extend self
。
例如,您可以使用 RG::Stats.sum(array)
调用该方法,如果您这样做,它仍然会被 instance_methods
方法列出:
module RG::Stats
extend self
def sum(a, args = {})
a.inject(0){ |accum, i| accum + i }
end
end
这样,sum
方法定义为实例方法,使用extend self
.
后包含在模块的单例class中
您可以检查 RG::Stats
模块的实例方法来验证这一点:
RG::Stats.instance_methods
=> [:sum]
使用这种技术,您不必担心没有 self
关键字定义方法,因为模块不能有实例,所以它不能像 RG::Stats
模块的实例方法那样被调用.由于 extend self
语句,它只能作为单例方法调用 RG::Stats.sum(array)
。
Class: RuboCop::Cop::Style::ModuleFunction
规则建议使用 module_function 使所有方法成为自我。
参考:https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/ModuleFunction
# bad
module Test
extend self
# ...
end
# good
module Test
module_function
# ...
end
我的模块定义如下所示:
module RG::Stats
def self.sum(a, args = {})
a.inject(0){ |accum, i| accum + i }
end
end
要使用此方法,我只需要包含此定义的文件即可:
RG::Stats.sum(array)
还有
RG::Stats.method(:sum)
但是,如果我需要知道使用 RG::Stats.instance_methods
的方法列表,我会得到一个空数组。这是因为我使用了self
。如果我省略 self
,那么 RG::Stats.instance_methods
会给出方法列表,但我无法再访问它们。
问题是:如何在模块的方法定义中使用self
?
如果你使用self
,那么你可以直接使用模块方法使用: RG::Stats.sum(array)
如上所述。
如果您不使用 self
在模块中定义方法,那么对于包含模块的 class,该方法将被包含为 instance_method
。
因此,您可以在 RG::Stats
模块中定义 sum
实例方法:
module RG::Stats
def sum(a, args = {})
a.inject(0){ |accum, i| accum + i }
end
end
然后,您可以在 class 中包含 RG::Stats
模块,然后 sum
方法将作为 instance_method
用于 [=38= 的对象]:
class YourClass
include RG::Stats
. . .
. . .
end
并且您可以在 YourClass
的实例上调用 sum
方法:
YourClass.new.sum
要回答您的问题,您可以使用 self
将您的方法定义为模块内的 class 方法,而不使用 self
将方法定义为实例方法,并且它取决于您的需要和用例,当您想要从模块方法中获得什么类型的行为时。
因为def self.sum
没有定义实例方法;您使用了错误的方法 select 它。试试这个:
RG::Stats.methods(false)
# => [:sum]
如果您希望仅在模块的单例 class 中定义方法(其中使用 self
定义的方法存在),请在每个方法定义中使用 self
。如果希望模块的方法同时定义为实例方法和单例方法,则省略self和extend self
。
例如,您可以使用 RG::Stats.sum(array)
调用该方法,如果您这样做,它仍然会被 instance_methods
方法列出:
module RG::Stats
extend self
def sum(a, args = {})
a.inject(0){ |accum, i| accum + i }
end
end
这样,sum
方法定义为实例方法,使用extend self
.
您可以检查 RG::Stats
模块的实例方法来验证这一点:
RG::Stats.instance_methods
=> [:sum]
使用这种技术,您不必担心没有 self
关键字定义方法,因为模块不能有实例,所以它不能像 RG::Stats
模块的实例方法那样被调用.由于 extend self
语句,它只能作为单例方法调用 RG::Stats.sum(array)
。
Class: RuboCop::Cop::Style::ModuleFunction
规则建议使用 module_function 使所有方法成为自我。
参考:https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/ModuleFunction
# bad
module Test
extend self
# ...
end
# good
module Test
module_function
# ...
end