Ruby中的模块函数定义

Ruby中的模块函数定义,ruby,Ruby,我正在学习1.9.3版的Ruby,遵循关于LearnRubythHardway的教程 似乎在模块中定义函数时,必须在函数名前面加上模块名,如下所示: module MyStuff def MyStuff.apple() puts "I AM APPLES!" end end MyStuff.apple() 为什么你不能这样做: module MyStuff def apple() puts "I AM APPLES!" end

我正在学习1.9.3版的Ruby,遵循关于LearnRubythHardway的教程

似乎在
模块中定义函数时,必须在函数名前面加上模块名,如下所示:

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文档中,有一个


我做错了什么?

在第一种情况下,您创建了一个类级方法,这意味着您可以直接在类/模块上调用它:
MyStuff.apple
。在第二个示例中,您创建了一个实例级方法,这意味着您需要一个实例来访问该方法:

class MyKlazz
    include MyStuff
end

obj=MyKlazz.new
obj.apple

模块是将方法、类和常量组合在一起的一种方式。模块为您带来两大好处: 模块提供名称空间并防止名称冲突。 模块实现了mixin功能

摘自

您可以改为:

module MyStuff
    def self.apple
        puts "I AM APPLES!"
    end
end

MyStuff.apple # "I AM APPLES!"
第一个例子

module MyStuff
  def MyStuff.apple()
    puts "I AM APPLES!"
  end
end
。。。之所以有效,是因为您在模块上而不是在模块中定义方法,这就是您在第二个示例中所做的:

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
)或者包含了该类的实例(即
Conrad.new.apple
),则定义了该类可用的方法。

这是因为您将
apple
定义为MyStuff上的实例方法,而且由于MyStuff本身不是一个实例,因此您不能在其上调用
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!"
    
  • 您可以
    MyStuff包含到类中,并在该类的实例上调用该方法:

    module MyStuff
      def apple
        puts "I AM APPLES!"
      end
    end
    
    class Foo; include MyStuff; end
    
    Foo.new.apple  #=> "I AM APPLES!"
    
  • 您可以
    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>

只是因为它是一个模块,没有类。你可能在寻找工厂模式?@BenjaminM将MyStuff设置为类而不是模块不会改变这种行为。
class Foo
  def bar; 42; end
  def self.bar; 24; end
end

Foo.bar      #=> 24
Foo.new.bar  #=> 42