我正在使用版本1.9.3学习Ruby,继续学习LearnRubyTheHardWay的教程。
似乎在Module
中定义函数时,必须在函数名前加上模块的名称,如下所示:
module MyStuff
def MyStuff.apple()
puts "I AM APPLES!"
end
end
MyStuff.apple()
为什么你不能这样做:
module MyStuff
def apple()
puts "I AM APPLES!"
end
end
MyStuff.apple() # this does not work
在Ruby文档中,有an example like the one above。
我出错了什么?
答案 0 :(得分:3)
模块是一种将方法,类和常量分组在一起的方法。模块为您带来两大好处: 模块提供命名空间并防止名称冲突。 模块实现了mixin工具。
取自(http://www.tutorialspoint.com/ruby/ruby_modules.htm)
您可以改为:
module MyStuff
def self.apple
puts "I AM APPLES!"
end
end
MyStuff.apple # "I AM APPLES!"
答案 1 :(得分:2)
在第一种情况下,您创建了一个类级方法,这意味着您可以直接在类/模块上调用它:MyStuff.apple
。在第二个中,您创建了一个实例级方法,这意味着您需要一个实例来访问该方法:
class MyKlazz
include MyStuff
end
obj=MyKlazz.new
obj.apple
答案 2 :(得分:1)
那是因为您在MyStuff上将apple
定义为实例方法,并且由于MyStuff不是其自身的实例,因此您无法在其上调用apple
。< / p>
要拨打apple
,您可以选择以下几种方法:
明确定义MyStuff
上的方法,如您所见:
module MyStuff
def MyStuff.apple
puts "I AM APPLES!"
end
end
MyStuff.apple #=> "I AM APPLES!"
但您不必明确此,并且可以使用self
代替MyStuff
:
module MyStuff
def self.apple
puts "I AM APPLES!"
end
end
MyStuff.apple #=> "I AM APPLES!"
您可以include
MyStuff进入一个类并在该类的实例上调用该方法:
module MyStuff
def apple
puts "I AM APPLES!"
end
end
class Foo; include MyStuff; end
Foo.new.apple #=> "I AM APPLES!"
你可以extend
MyStuff进入一个类或模块 - 这包括MyStuff本身:
module MyStuff
extend self
def apple
puts "I AM APPLES!"
end
end
MyStuff.apple #=> "I AM APPLES!"
module OtherStuff; extend MyStuff; end
OtherStuff.apple #=> "I AM APPLES!"
这与课程的工作方式非常相似。例如,这不起作用:
class Foo
def bar; 42; end
end
Foo.bar #=> #<NoMethodError: undefined method `bar' for Foo:Class>
因为bar
同样是一个实例方法,所以你需要创建一个实例或者使bar
成为一个类方法:
class Foo
def bar; 42; end
def self.bar; 24; end
end
Foo.bar #=> 24
Foo.new.bar #=> 42
答案 3 :(得分:0)
第一个例子......
module MyStuff
def MyStuff.apple()
puts "I AM APPLES!"
end
end
...之所以有效,是因为你在模块上定义了方法,而不是模块中的IN,这就是你在第二个例子中所做的:
module MyStuff
def apple()
puts "I AM APPLES!"
end
end
如果你有一个班级并做同样的事情,那就类似了:
class Conrad
def Conrad.apple()
puts "I AM APPLES"
end
end
您也可以使用def self.apple()
,这意味着相同:
class Conrad
def self.apple()
puts "I AM APPLES"
end
end
在这两种情况下,您都是在类本身上定义一个方法而不是该类的实例。
对于模块,如果扩展了该类(即Conrad.apple
),那么您将定义一个可供类使用的方法,或者如果包含该类,则定义该类的实例(即{{1 }})。