从Ruby中的模块/mixins继承类方法 [英] Inheriting class methods from modules / mixins in Ruby
问题描述
众所周知,在Ruby中,类方法被继承:
It is known that in Ruby, class methods get inherited:
class P
def self.mm; puts 'abc' end
end
class Q < P; end
Q.mm # works
但是,令我惊讶的是它不适用于mixins:
However, it comes as a surprise to me that it does not work with mixins:
module M
def self.mm; puts 'mixin' end
end
class N; include M end
M.mm # works
N.mm # does not work!
我知道#extend方法可以做到这一点:
I know that #extend method can do this:
module X; def mm; puts 'extender' end end
Y = Class.new.extend X
X.mm # works
但是我正在写一个既包含实例方法又包含类方法的mixin(或更确切地说,是想写):
But I am writing a mixin (or, rather, would like to write) containing both instance methods and class methods:
module Common
def self.class_method; puts "class method here" end
def instance_method; puts "instance method here" end
end
现在我要做的是:
class A; include Common
# custom part for A
end
class B; include Common
# custom part for B
end
我希望A,B从Common
模块继承实例和类方法.但是,那当然是行不通的.因此,难道没有从单个模块进行继承的秘密方法吗?
I want A, B inherit both instance and class methods from Common
module. But, of course, that does not work. So, isn't there a secret way of making this inheritance work from a single module?
对我来说,将其分为两个不同的模块似乎并不明智,一个模块包含其中,另一个模块进行扩展.另一种可能的解决方案是使用类Common
而不是模块.但这只是一个解决方法. (如果有两组通用功能Common1
和Common2
并且我们确实需要mixins怎么办?)有什么深层原因导致类方法继承不能从mixins继承?
It seems inelegant to me to split this into two different modules, one to include, the other to extend. Another possible solution would be to use a class Common
instead of a module. But this is just a workaround. (What if there are two sets of common functionalities Common1
and Common2
and we really need to have mixins?) Is there any deep reason why class method inheritance does not work from mixins?
推荐答案
一个常见的习惯用法是使用included
钩子并从那里注入类方法.
A common idiom is to use included
hook and inject class methods from there.
module Foo
def self.included base
base.send :include, InstanceMethods
base.extend ClassMethods
end
module InstanceMethods
def bar1
'bar1'
end
end
module ClassMethods
def bar2
'bar2'
end
end
end
class Test
include Foo
end
Test.new.bar1 # => "bar1"
Test.bar2 # => "bar2"
这篇关于从Ruby中的模块/mixins继承类方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!