是否可以混入模块方法?
Is it possible to mix-in a module method?
假设我有一个模块声明了一个模块方法(不是一个实例方法):
module M
def self.foo
puts 'foo'
end
end
现在假设我想将 M.foo
混合到另一个 class C
中,这样就定义了 C.foo
。
最后,我想这样做 而不改变 M.foo
的定义方式 和 而不仅仅是在 C
中创建方法调用 M.foo
。 (即重写 foo
作为实例方法不算数。使用 module_function
也不算数。)
这在 Ruby 中不可能吗?
I want to do this without changing the way M.foo
is defined
很遗憾,这是不可能的。 Ruby 只允许包含模块,而不是 classes。然而,foo
是在 M
的单例 class 上定义的,其中 是 一个 class。因此,你不能 include
它。同样的限制适用于 extend
。尝试这样做会导致 TypeError
:
module M
def self.foo
puts 'foo'
end
end
class C
extend M.singleton_class # TypeError: wrong argument type Class (expected Module)
end
然而,您可以通过将 foo
定义为单独模块中的实例方法来实现您想要的,然后可以通过 [=17] 将其混合到 M
和 C
中=]:(该模块不必嵌套在 M
下)
module M
module SingletonMethods
def foo
puts 'foo'
end
end
extend SingletonMethods # <- this makes foo available as M.foo
end
class C
extend M::SingletonMethods # <- this makes foo available as C.foo
end
或者使用 Ruby 的 included
回调进行一些元编程魔法:
module M
module SingletonMethods
def foo
puts 'foo'
end
end
extend SingletonMethods
def self.included(mod)
mod.extend(SingletonMethods)
end
end
class C
include M
end
这是 ActiveSupport::Concern
在 Rails 中工作方式的简化版本。
假设我有一个模块声明了一个模块方法(不是一个实例方法):
module M
def self.foo
puts 'foo'
end
end
现在假设我想将 M.foo
混合到另一个 class C
中,这样就定义了 C.foo
。
最后,我想这样做 而不改变 M.foo
的定义方式 和 而不仅仅是在 C
中创建方法调用 M.foo
。 (即重写 foo
作为实例方法不算数。使用 module_function
也不算数。)
这在 Ruby 中不可能吗?
I want to do this without changing the way
M.foo
is defined
很遗憾,这是不可能的。 Ruby 只允许包含模块,而不是 classes。然而,foo
是在 M
的单例 class 上定义的,其中 是 一个 class。因此,你不能 include
它。同样的限制适用于 extend
。尝试这样做会导致 TypeError
:
module M
def self.foo
puts 'foo'
end
end
class C
extend M.singleton_class # TypeError: wrong argument type Class (expected Module)
end
然而,您可以通过将 foo
定义为单独模块中的实例方法来实现您想要的,然后可以通过 [=17] 将其混合到 M
和 C
中=]:(该模块不必嵌套在 M
下)
module M
module SingletonMethods
def foo
puts 'foo'
end
end
extend SingletonMethods # <- this makes foo available as M.foo
end
class C
extend M::SingletonMethods # <- this makes foo available as C.foo
end
或者使用 Ruby 的 included
回调进行一些元编程魔法:
module M
module SingletonMethods
def foo
puts 'foo'
end
end
extend SingletonMethods
def self.included(mod)
mod.extend(SingletonMethods)
end
end
class C
include M
end
这是 ActiveSupport::Concern
在 Rails 中工作方式的简化版本。