从Ruby中的模块/mixins继承类方法 [英] Inheriting class methods from modules / mixins in Ruby

查看:61
本文介绍了从Ruby中的模块/mixins继承类方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

众所周知,在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而不是模块.但这只是一个解决方法. (如果有两组通用功能Common1Common2并且我们确实需要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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆