在这个Ruby代码中:
Module M
Class C < Struct.new(:param)
def work
M::helper(param)
end
end
def helper(param)
puts "hello #{param}"
end
end
当我尝试运行
时,我收到“未定义方法'助手',因为'M:模块'”错误c = M::C.new("world")
c.work
但直接从另一个类调用M::helper("world")
可以正常工作。类可以不调用在它们定义的同一模块中定义的模块函数吗?有没有办法解决这个问题,除了将课程移到模块之外?
答案 0 :(得分:4)
你应该在self
之前添加模块方法:
module M
class C < Struct.new(:param)
def work
M::helper(param)
end
end
def self.helper(param)
puts "hello #{param}"
end
end
答案 1 :(得分:4)
要调用M::helper
,您需要将其定义为def self.helper; end
为了便于比较,请查看以下修改后的代码段
module M
class C < Struct.new(:param)
include M # include module to get helper2 mixed in
def work
M::helper(param)
helper2(param)
end
end
def self.helper(param)
puts "hello #{param}"
end
def helper2(param)
puts "Mixed in hello #{param}"
end
end
c = M::C.new("world")
c.work
答案 2 :(得分:2)
C
不在helper
的单件类时, M
正试图在helper
上致电M
。另外,当它只是一种方法时,你会一直说helper
是一个模块函数。使helper
模块函数可以使代码工作:
module M
class C < Struct.new(:param)
def work
M::helper(param)
end
end
module_function
def helper(param)
puts "hello #{param}"
end
end
在课程中包含该模块也可以:
module M
class C < Struct.new(:param)
include M
def work
helper(param)
end
end
def helper(param)
puts "hello #{param}"
end
end
在第一个示例中,helper
被放入M
的单身类module_function
。第二个示例将M
的方法导入C
,以便C
可以使用它们。另一个区别是,在第一个中,您可以从代码中的任何位置调用M.helper
。在第二个中,您可以在代码中的helper
的任何实例中调用C
。要解决此问题,请将helper
设为私有:
module M
class C < Struct.new(:param)
include M
def work
helper(param)
end
end
private
def helper(param)
puts "hello #{param}"
end
end
答案 3 :(得分:1)
以下是一些解释:
来自ruby docs。
模块内的模块是方法和常量的集合。模块中的方法可以是实例方法或模块方法。当包含模块时,实例方法在类中显示为方法,而模块方法则不包括。 相反,可以在不创建封装对象的情况下调用模块方法,而实例方法则可以不调用。 (参见模块#module_function。)
self.methodname
创建模块方法。
在这种情况下,当你从C ++开发人员的角度来看它时,你调用M::helper
实际上是M.helper
。在这种情况下,接收器是Module对象(ruby builtin type Module的一个实例)。
查看这个的其他方法是理解接收器概念,每个方法调用都包含一个接收器和方法名称(+可选的params和代码块)。 Receiver可以是Module object
,Class object
或用户定义类的实例。
您只能在Module(或Class)对象上调用Module(或Class)方法。您可以在实例上调用任何方法(模块/类/实例)。
如果要调用模块中定义的实例方法,则必须通过including
在某个类中为该模块提供接收器并创建其实例。
因此,在这种情况下,另一种解决方案可以是:
module MM
def helper(param)
puts "hello #{param}"
end
class ReceiverClass
include MM # add helper() to ReceiverClass
end
class C < Struct.new(:param)
def work
ReceiverClass.new.helper(param)
end
end
end
c = MM::C.new("world")
c.work