是否可以混合模块方法?
Posted
技术标签:
【中文标题】是否可以混合模块方法?【英文标题】:Is it possible to mix-in a module method? 【发布时间】:2020-05-02 19:24:36 【问题描述】:假设我有一个声明模块方法的模块(不是实例方法):
module M
def self.foo
puts 'foo'
end
end
现在假设我想将M.foo
混合到另一个类C
中,这样C.foo
就被定义了。
最后,我想这样做不改变M.foo
的定义方式 并且不只是在C
中创建一个调用M.foo
的方法。 (即将foo
重写为实例方法不算数。使用module_function
也不算数。)
这在 Ruby 中是不可能的吗?
【问题讨论】:
没有。如果您的意图是在类C
中混合成为类方法的方法,则必须使模块中的方法成为实例方法并使用C.extend M
(或C.singleton_class.include M
)。 (见Object#extend)。要使用模块方法,您必须调用定义它的模块上的方法,模块Math 的方法就是一个例子。
@CarySwoveland 完美答案!谢谢。
作为学术练习,您可以将M
上的所有类方法复制到实例方法中,但最好只修改M
以首先将定义作为实例方法并可能@ 987654337@如果需要(或使用module_method
)
【参考方案1】:
我想这样做不改变
M.foo
的定义方式
很遗憾,这是不可能的。 Ruby 只允许包含模块,而不是类。 foo
是在 M
的单例类上定义的,是一个类。因此,您不能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
定义为单独模块中的实例方法来实现您想要的,然后可以通过 extend
将其混合到 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 中工作方式的简化版本。
【讨论】:
一个不错的简单答案,谢谢。这基本上是我在阅读 MRI 源后得出的结论——很高兴在这里以“官方”形式记录它。 @pje 你的问题启发了我问这个问题:***.com/q/59766403/477037 多么有趣的问题啊!我以前从没想过。以上是关于是否可以混合模块方法?的主要内容,如果未能解决你的问题,请参考以下文章
将 typescript 定义文件与 nodejs 混合需要内部模块中的多个文件
是否可以将 kubeflow 组件与 tensorflow 扩展组件混合使用?