Ruby:可以在模块中定义类方法吗?
假设有三类:Ruby:可以在模块中定义类方法吗?,ruby,Ruby,假设有三类:A,B&C。我希望每个类都有一个类方法,比如说self.foo,它对于a,B,C有完全相同的代码 是否可以在模块中定义self.foo,并将此模块包括在a、B和C中?我试图这样做,但收到一条错误消息,说无法识别foo。是的 module Foo def self.included(base) base.extend(ClassMethods) end module ClassMethods def some_method # stuff
A
,B
&C
。我希望每个类都有一个类方法,比如说self.foo
,它对于a
,B
,C
有完全相同的代码
是否可以在模块中定义self.foo
,并将此模块包括在a
、B
和C
中?我试图这样做,但收到一条错误消息,说无法识别foo
。是的
module Foo
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def some_method
# stuff
end
end
end
我应该补充一个可能的注意事项——如果模块将是所有类方法——最好在模型中使用extend ModuleName
,并直接在模块中定义方法,而不是在模块中有一个ClassMethods模块
module ModuleName
def foo
# stuff
end
end
或者,您可以在以后扩展这些类:
class A
end
class B
end
class C
end
[A, B, C].each do |klass|
klass.extend Common
end
Rails 3引入了一个名为
ActiveSupport::Concern
的模块,其目标是简化模块的语法
module Foo
extend ActiveSupport::Concern
module ClassMethods
def some_method
# stuff
end
end
end
它允许我们在模块中保存几行“样板”代码。这是使ruby如此特殊的基本ruby mixin功能。 当
extend
将模块方法转换为类方法时,include
将模块方法转换为include/extensing类或模块中的实例方法
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'
只是想扩展奥利弗的答案 在模块中一起定义类方法和实例方法
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)
Ruby实际上没有静态方法的概念。在ruby中,所有方法都有一个receiver对象。它可能只是一个碰巧有
class
或Module
的class
的方法。在这种情况下,foo
不是a、B和C的实例方法吗?正如Andrew已经指出的,Ruby的方法总是实例方法。但在本例中,实例是类。所以,foo
是类实例方法。用类作为接收者调用它:a.foo
。在A的实例方法中,还可以使用self.class.foo
@MladenJablanović那么,实例通常用于引用类生成的对象,而不是类对象本身。为了避免混淆,我建议将它们称为类方法而不是类实例方法;扩大共同利益;end相当于A类;包括普通单件;结束
。感谢您展示了包含
和扩展
之间的区别。
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)