在 Ruby 中的模块中包含模块时如何解决命名空间冲突?
这是我的代码的样子:
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 的签名。我只能主要编辑自己的类;我可以编辑模块 A 和 B,但许多现有代码都使用它们(因此,例如,无需将 foo 更改为 A.foo)。我正在考虑这样做
class MyClass
module MyModules
include B
end
....
MyModules.bar
....
end
但这不起作用。
在执行 include B 时如何“本地化”命名空间?
Here is what my code looks like:
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
When I call "C.test" I get "X" instead of "A" (which is what I want) because the local definition of foo has overridden that in A. I can't change the signature of either foo's. I can only mainly edit my own class; I can edit modules A and B but lots of existing code use them and they are (so no changing foo to A.foo for instance). I am thinking of doing
class MyClass
module MyModules
include B
end
....
MyModules.bar
....
end
But this does not work.
How can I "localize" the namespace when doing include B?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
据我了解,您想要覆盖
MyClass
内的A#foo
(B#bar
也使用它)。但是,您只想在MyClass
内重写它,而不是B
mixin 中的代码。这里需要理解的是,当
A
和B
mixin 的代码运行时,它们将成为MyClass
实例的一部分。因此,不可能在不影响 mixin 的情况下重写MyClass
的实例方法。这就好像 mixin 的方法被扔进一个桶(MyClass
实例)中,然后运行。他们没有单独的范围。因此,简单的答案是:不,你不能这样做。不过,可能有几种可能的解决方案,其中许多闻起来像意大利面。遇到这样的问题可能表明整体设计决策需要进行一些重构。
回顾模块的基础知识:
这是因为该方法是作为类方法添加的。
include
来救援:因此,
include
将所有方法堆放在一个公共实例中,但我们仍然可以使用super
来调用包含的方法我们压倒一切。如果您寻求面食方面的解决方案,您也许可以在bar
方法中使用 super,有条件地调用您要重写的方法。此外,根据情况,您可以设置一个新模块,并使用包含您需要访问的方法的模块来扩展它,就像您添加的答案中一样。
From what i understand, you want to override
A#foo
(which is also used byB#bar
) insideMyClass
. However, you only want to override it insideMyClass
, and not for the code in theB
mixin.The thing to understand here, is that when the code of the
A
andB
mixins are run, they will be part of aMyClass
instance. Therefore, it is impossible to override the instance methods ofMyClass
without affecting the mixins. It is as if the methods of the mixins were thrown into a bucket (theMyClass
instance), and then run. They do not have separate scopes. Therefore, the simple answer is: no, you can not do it.There could be several possible solutions though, many of which smell like pasta. Running into problems like this one could be an indication that the overall design decisions need some refactoring.
Going over the basics of modules:
This is because the method was added as a class method.
include
to the rescue:So,
include
heaps all the methods together into one common instance, but we can still usesuper
to call an included method that we were overriding. If you go for a solution on the pasta side, you might be able to use super inside thebar
method, conditionally invoking the method you were overriding.Also, depending on the case, you could set up a new module and
extend
it with the module containing the methods you need access too, like in the answer you added.我找到了我想要的解决方案,可能不是最好的答案,但完全按照我想要的方式工作。
这有效地允许我限制 B 和本地类 MyModules 中所有其他包含的模块的范围。在我的代码中,它实际上是有意义的,因为所有包含的模块都处理表达式操作,因此我可以调用本地类“Expr”(并且它们现在严重过度使用名称“eval”、“bind”和“free”)。
I found a solution for what I wanted, might not be the best answer but works exactly the way I want it to.
This effectively allows me to limit the scope of B and all other included modules in the local class MyModules. In my code it actually has a meaning because all the included modules handle expression manipulation so I can call the local class "Expr" (and they are seriously overusing the names 'eval', 'bind' and 'free' right now).