ruby包括方法名称冲突

时间:2017-09-17 14:32:37

标签: ruby

如果一个类包含许多模块,并且从包含来自其原始模块的include调用私有方法,并且私有方法存在于具有相同名称的其他模块中,则它应该使用其自己的模块中的定义。在代码中:

module C
  def c
    puts collision
  end
  private
  def collision
    'c'
  end
end
module B
  def b
    puts collision
  end
  private
  def collision
    'b'
  end
end
class A
  include B
  include C
end
A.new.b
# => 'c'

我希望A.new.b能够'b'A.new.c提供'c',但会发生冲突,因为它们使用相同的私有方法名称。在包含许多包含的大型项目中,如何避免这种情况?

2 个答案:

答案 0 :(得分:2)

你期待一些魔法,但不存在。

include是一个普通的好混合。一旦被调用,它只是将包含模块中声明的所有方法“插入”到调用include的模块中。

因此你最终得到了类似的东西:

class A
public
  def c; ... end
private
  def collision; ... end
public
  def b; ... end
private
  def collision; ... end
end

由于ruby开放类概念,后一个私有方法collision显然优先于前者。

答案 1 :(得分:1)

我认为真正的问题是:我如何确保我的模块没有使用其他模块方法(这些方法意外地具有相同的名称)。

如果您可以确保模块方法不依赖于状态并将它们定义为模块方法并以这种方式使用它,那将是最好的。因此,您明确使用任何helping方法,如下所示:

module C
  def c
    puts C.collision
  end
  def self.collision
    'c'
  end
end

module B
  def b
    puts B.collision
  end
  def self.collision
    'b'
  end
end

class A
  include B
  include C
end

A.new.b # b
A.new.c # c

如果您想将它们设为私有,可以使用一些额外的代码,您可以阅读一篇明确的文章:https://6ftdan.com/allyourdev/2015/05/02/private-module-methods-in-ruby/

正如this answer中所述,你可以开启它以使其发挥作用。包含机制非常简单,(IMO)它应该保持这种方式。当你意识到这个碰撞问题时 - 你现在可以避免它。

如果您不喜欢这种方法,您还可以将实际工作封装在一个类中,并使用模块进行包含:

  module C
    def c
      MyLibStuff::ClassDoingRealWork.no_collision_here_anymore(any, param, if_needed)
    end
  end