这是我的代码:
module A
def foo
puts "A"
end
end
module B
include A
def bar
foo
end
end
class MyClass
include B
def foo
puts "X"
end
def self.test
puts bar
end
end
当我调用“C.test”时,我得到的是“X”而不是“A”(这是我想要的),因为 foo 的本地定义已经覆盖了 A 中的定义。我无法更改任何一个 foo 的签名.我只能主要编辑自己的类(class);我可以编辑模块 A 和 B,但许多现有代码都在使用它们,而且它们确实如此(例如,无需将 foo 更改为 A.foo)。我正在考虑做
class MyClass
module MyModules
include B
end
....
MyModules.bar
....
end
但这行不通。
在执行 include B 时如何“本地化”命名空间?
最佳答案
据我了解,您想覆盖 MyClass
中的 A#foo
(B#bar
也使用它)。但是,您只想在 MyClass
中覆盖它,而不是在 B
mixin 中覆盖它。
这里要理解的是,当 A
和 B
混入的代码运行时,它们将成为 MyClass
实例。因此,不可能在不影响混入的情况下覆盖 MyClass
的实例方法。就好像 mixins 的方法被扔进了一个桶(MyClass
实例),然后运行。它们没有单独的作用域。因此,简单的回答是:不,你做不到。
虽然可能有几种可能的解决方案,其中许多都是 smell like pasta .遇到这样的问题可能表明整体设计决策需要进行一些重构。
复习模块的基础知识:
module Numbered
DEFAULT = "1234-AWESOME"
def serial_number
DEFAULT
end
def self.awesome?
true
end
end
Numbered.awesome? # => true
Numbered.serial_number # whoops! NoMethodError.
o = Object.new
o.extend(Numbered)
o.serial_number #=> "1234-AWESOME"
Numbered.extend(Numbered)
Numbered.serial_number # => "1234-AWESOME"
class Dog
extend Numbered
end
Dog.serial_number # => "1234-AWESOME"
Dog::DEFAULT # => "1234-AWESOME"
fido = Dog.new
fido.serial_number # NoMethodError!
这是因为该方法是作为类方法添加的。 include
来拯救:
class Fish
include Numbered
def serial_number
super + '-FSH'
end
end
cod = Fish.new
cod.serial_number # => "1234-AWESOME-FSH"
因此,include
将所有方法堆放在一个公共(public)实例中,但我们仍然可以使用 super
调用我们覆盖的包含方法。如果您在意大利面方面寻求解决方案,您可以在 bar
方法中使用 super,有条件地调用您覆盖的方法。
此外,根据具体情况,您可以设置一个新模块并使用包含您需要访问的方法的模块扩展
它,就像您添加的答案中那样。
关于ruby - 在 Ruby 的模块中包含模块时如何解决 namespace 冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6704573/