2

我正在学习 1.9.3 版的 Ruby,遵循 LearnRubyTheHardWay 上的教程。

似乎当您在 a 中定义函数时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 文档中,有一个类似上述示例的示例

我怎么了?

4

4 回答 4

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!"
于 2013-03-02T15:07:15.193 回答
2

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

class MyKlazz
    include MyStuff
end

obj=MyKlazz.new
obj.apple
于 2013-03-02T15:07:12.217 回答
2

那是因为您在 MyStuff 上定义apple实例方法,并且由于 MyStuff 不是其自身的实例,因此您无法调用apple它。

为了打电话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!"
    
  • 您可以includeMyStuff 进入一个类并在该类的实例上调用该方法:

    module MyStuff
      def apple
        puts "I AM APPLES!"
      end
    end
    
    class Foo; include MyStuff; end
    
    Foo.new.apple  #=> "I AM APPLES!"
    
  • 您可以将extendMyStuff 放入一个类或模块中——这包括 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
于 2013-03-02T15:12:27.030 回答
0

第一个例子...

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

于 2013-03-02T15:10:04.277 回答