我正在使用另一个名称空间中的模块。具体来说,我使用的是其中定义的类方法(在此示例中为class_method_message
)。
我现在想更改模块的某些行为,因此我想创建一个新模块,扩展原始模块,并覆盖我想更改的方法。
这显示在下面,似乎没有按预期工作。
module OriginalSpace
module OriginalModuleThatICantEdit
def self.class_method_message
puts "the message is: #{get_message}"
end
def self.get_message
"hello"
end
end
end
module MySpace
module MyExtensionOfThatModule
extend OriginalSpace::OriginalModuleThatICantEdit
def self.get_message
"byebye"
end
end
end
# This works
OriginalSpace::OriginalModuleThatICantEdit.class_method_message
# This doesn't: `undefined method `class_method_message' for MySpace::MyExtensionOfThatModule:Module (NoMethodError)`
MySpace::MyExtensionOfThatModule.class_method_message
我在做什么错了?
答案 0 :(得分:1)
OriginalSpace::OriginalModuleThatICantEdit
在OriginalSpace::OriginalModuleThatICantEdit.singleton_class.prepend(Module.new do
def get_message
"byebye"
end
end)
OriginalSpace::OriginalModuleThatICantEdit.class_method_message
#⇒ the message is: byebye
的本征类中定义。也就是说,扩展后者没有多大意义,您需要扩展其本征类。
此处使用新功能更新原始模块的常用方法是使用Module#prepend
在特征类之前添加所需的行为:
class_method_message
请注意,get_message
和include
都在本征类上声明,本征类是 class 而不是 module 。也就是说,不能仅仅使用extend
和/或{{1}}将它们导入模块。
答案 1 :(得分:0)
也许我遗漏了一些东西,但是如果您想更改模块的功能,为什么不直接做它,而不是诉诸于包含,添加或扩展另一个模块呢?它更直接,您可以删除方法以及添加或修改方法。
module OriginalSpace
module OriginalModuleThatICantEdit
def self.class_method_message
puts "the message is: #{get_message}"
end
def self.huh
"huh"
end
def self.get_message
"hello"
end
end
end
OriginalSpace::OriginalModuleThatICantEdit.class_method_message
#=> "the message is: hello"
OriginalSpace::OriginalModuleThatICantEdit.methods(false)
#=> [:class_method_message, :huh, :get_message]
让我们删除( module 方法)huh
,然后重新定义get_message
。
module OriginalSpace
module OriginalModuleThatICantEdit
singleton_class.send(:undef_method, :huh)
def self.get_message
"byebye"
end
end
end
OriginalSpace::OriginalModuleThatICantEdit.class_method_message
#=> "the message is: byebye"
OriginalSpace::OriginalModuleThatICantEdit.methods(false)
#=> [:class_method_message, :get_message]
我们必须在send
中使用singleton_class.send(:undef_method, :huh)
,因为https://github.com/JeffreyWay/laravel-mix/issues/1172是私有方法。
答案 2 :(得分:-3)
只是一个建议。
除了创建新模块以外,您还可以使用module_eval覆盖现有模块。