考虑我有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)?
谢谢!
答案 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(通过include
或extend
使用)并且可以直接调用:
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