module Test
def self.model_method
puts "this is a module method"
end
end
class A
include Test
end
A.model_method
这将是错误的:
未定义的方法`model_method'用于A:Class(NoMethodError)
但是当我使用A的元类时,它可以工作:
module Test
def model_method
puts "this is a module method"
end
end
class A
class << self
include Test
end
end
A.model_method
有人可以解释一下吗?
答案 0 :(得分:32)
如果您希望在包含模块时将类方法和实例方法混合到类中,则可以遵循以下模式:
module YourModule
module ClassMethods
def a_class_method
puts "I'm a class method"
end
end
def an_instance_method
puts "I'm an instance method"
end
def self.included(base)
base.extend ClassMethods
end
end
class Whatever
include YourModule
end
Whatever.a_class_method
# => I'm a class method
Whatever.new.an_instance_method
# => I'm an instance method
基本上过度简化它,你extend
添加类方法,include
添加实例方法。当包含一个模块时,它会调用#included
方法,并包含它所包含的实际类。从这里你可以extend
使用另一个模块的类方法{{1}}。这是一种非常常见的模式。
另请参阅:http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
答案 1 :(得分:11)
包含模块类似于复制其实例方法。
在您的示例中,没有要复制到A
的实例方法。 model_method
实际上是Test
的单例类的实例方法。
假设:
module A
def method
end
end
此:
module B
include A
end
类似于:
module B
def method
end
end
当你这样想的时候,这很有道理:
module B
class << self
include A
end
end
B.method
这里,方法被复制到B
模块的单例类,这使它们成为B
的“类方法”。
请注意,这与:
完全相同module B
extend A
end
实际上,这些方法并没有被复制; 没有重复。该模块只包含在方法查找列表中。