如何使用类对象 - ruby​​调用模块内的方法(2个不同模块中的方法名称相同)

时间:2017-07-06 16:09:13

标签: ruby

考虑我有2个模块,两个模块都包含功能' foo'。如果我需要使用包含它的类的对象来调用Module1的foo,我需要如何调用?

代码示例:

    module Module1
      def foo
        puts 'first one'
      end
    end

    module Module2
      def foo
        puts 'second one'
      end
    end



  class ClassName
      include Module1
      include Module2

      def initialize
        Module1.instance_method(:foo).bind( self ).call
        Module2.instance_method(:foo).bind( self ).call
      end
    end

    cls = ClassName.new

如何使用对象' cls'来调用方法foo。 (如果我需要调用Module1&f 39)?

谢谢!

3 个答案:

答案 0 :(得分:2)

如果你想保留通常的实例方法语义,最简单的解决方案可能是在include第二个模块之前为方法添加别名:

class ClassName
  include Module1
  alias :module_1_foo :foo
  include Module2
end

cls = ClassName.new
cls.module_1_foo
# => first one
cls.foo
# => second one

在repl.it上查看:https://repl.it/JQ73

或者,您可以将Module1.instance_method(:foo)返回的UnboundMethod对象传递给define_method

class ClassName
  include Module1
  include Module2
  define_method(:module_1_foo, Module1.instance_method(:foo))
end

这两个问题的警告是,如果Module1中有其他实例方法调用foo,他们最终会调用Module2#foo。他们无法知道Method1#foo已被重命名。"这至多是一个权宜之计,如果你的代码有任何复杂性,你应该重新设计整个事情,这样你就不会发生名称冲突。

答案 1 :(得分:1)

您始终可以将模块设为mixins(通过includeextend使用)并且可以直接调用:

module Module1
  def foo
    puts 'first one'
  end

  extend self
end

然后您可以随时拨打Module1.foo。请记住,当这种方式调用它时,它位于模块的上下文中,而不是任何可能已导入它的类。

bind(self)这个技巧是一个应该避免的严重骚扰。几乎在每种情况下,您都可以重新设计代码,以便在更普通的Ruby代码中更自然地表达。

答案 2 :(得分:0)

不那么干,但这也有效。

class ClassName
  include Module1
  include Module2

  def initialize
    Module1.instance_method(:foo).bind( self ).call
    Module2.instance_method(:foo).bind( self ).call
  end

  def call_foo_from_M1
    Module1.instance_method(:foo).bind( self ).call
  end

  def call_foo_from_M2
    Module2.instance_method(:foo).bind( self ).call
  end

end

cls = ClassName.new
cls.call_foo_from_M1  # first one
cls.call_foo_from_M2  # second one