假设有三个班级:A
,B
& C
。我希望每个类都有一个类方法,比如说self.foo
,它与A
,B
&的代码完全相同。 C
。
是否可以在模块中定义self.foo
,并将此模块包含在A
,B
& C
?我尝试这样做并收到一条错误消息,指出foo
无法识别。
答案 0 :(得分:95)
是的
module Foo
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def some_method
# stuff
end
end
end
我应该添加一个可能的注释 - 如果模块将成为所有类方法 - 最好只使用模型中的extend ModuleName
并直接在模块中定义方法 - 而不是在内部使用ClassMethods模块模块,la
module ModuleName
def foo
# stuff
end
end
答案 1 :(得分:42)
module Common
def foo
puts 'foo'
end
end
class A
extend Common
end
class B
extend Common
end
class C
extend Common
end
A.foo
或者,您可以在以后扩展课程:
class A
end
class B
end
class C
end
[A, B, C].each do |klass|
klass.extend Common
end
答案 2 :(得分:20)
Rails 3引入了一个名为ActiveSupport::Concern
的模块,其目标是简化模块的语法。
module Foo
extend ActiveSupport::Concern
module ClassMethods
def some_method
# stuff
end
end
end
它允许我们在模块中保存几行“样板”代码。
答案 3 :(得分:17)
这是ruby mixin的基本功能,使ruby如此特别。
虽然extend
将模块方法转换为类方法,但include
将模块方法转换为包含/扩展类或模块中的实例方法。
module SomeClassMethods
def a_class_method
'I´m a class method'
end
end
module SomeInstanceMethods
def an_instance_method
'I´m an instance method!'
end
end
class SomeClass
include SomeInstanceMethods
extend SomeClassMethods
end
instance = SomeClass.new
instance.an_instance_method => 'I´m an instance method!'
SomeClass.a_class_method => 'I´m a class method'
答案 4 :(得分:0)
只想扩展Oliver的答案 在模块中一起定义Class方法和实例方法。
module Foo
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def a_class_method
puts "ClassMethod Inside Module"
end
end
def not_a_class_method
puts "Instance method of foo module"
end
end
class FooBar
include Foo
end
FooBar.a_class_method
FooBar.methods.include?(:a_class_method)
FooBar.methods.include?(:not_a_class_method)
fb = FooBar.new
fb.not_a_class_method
fb.methods.include?(:not_a_class_method)
fb.methods.include?(:a_class_method)