创建一个模块,该模块使用相同的方法(但不同的实现)委托其他两个模块的使用

时间:2014-04-10 23:01:16

标签: ruby metaprogramming

这可能吗?

具体地

module A
  def foo
    puts "a"
  end
end

module B
  def foo
    puts "b"
  end
end

module C
  def foo
   if self.name=='Frank'
    #send to A.foo
   elsif self.name=='Bob'
    #send to B.foo
   end
  end
end

class Person
  include C
  attr_accessor :name
  def initialize(name)
   self.name=name
  end
end

f=Person.new('frank').foo # => "a"
f.name="Bob"
f.foo # => "b"

此外,假设模块A和B是第三方,无法修改。

换句话说,我希望将A和B都包含在Person类中,但是根据类实例的状态动态选择使用哪个方法。

1 个答案:

答案 0 :(得分:0)

这是一种方法:

<强>代码

module A
  def foo
    puts "a"
  end
end

module B
  def foo
    puts "b"
  end
end

module C
  include A
  alias :fooA :foo
  include B
  alias :fooB :foo 
  def foo
    if self.name =='Frank'
      fooA
    elsif self.name == 'Bob'
      fooB
    end
  end
end

class Person
  include C
  attr_accessor :name
  def initialize(name)
   self.name=name
  end
end

示例

f=Person.new('Frank')
f.foo        # => "a"
f.name="Bob"
f.foo        # => "b"

<强>解释

  • 解析代码后,module A
  • 中会包含module C
  • 方法:foo(来自module A)被分配了一个别名:fooA,因此module C现在包含方法:fooAfoo
  • module B包含在module C
  • 来自:foo的方法module B会覆盖:foo
  • 方法:foo(来自module B)被分配了一个别名:fooB,因此module C现在包含:fooAfooB和{ {1}}(来自foo
  • 使用module B创建方法foo,从def覆盖foo
  • module B包含class Person时,它会混合三种实例方法,module C:fooA:fooB