代码之家  ›  专栏  ›  技术社区  ›  pje

是否可以混合使用模块方法?

  •  0
  • pje  · 技术社区  · 5 年前

    假设我有一个模块,它声明了一个模块方法( 实例方法):

    module M
      def self.foo
        puts 'foo'
      end
    end
    

    现在,假设我想融入其中 M.foo 进入另一个班级 C 这样 C.foo 定义。

    最后,我想这样做 不改变方式 M.foo 已定义 而不只是在中创建一个方法 C 这叫 M.foo (即重写 foo 因为实例方法不算数。也不使用 module_function .)

    这在Ruby中是不可能的吗?

    0 回复  |  直到 5 年前
        1
  •  2
  •   Stefan    5 年前

    我想这么做 不改变方式 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 作为单独模块中的实例方法,该模块然后可以混合到两者中, 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中工作。