Ruby: 模块,需要和包含

56
我正在尝试使用Ruby模块(混入)。
我有test.rb:
#!/usr/bin/env ruby
require_relative 'lib/mymodule'

class MyApp
  include MyModule
  self.hallo
end

和 lib/mymodule.rb:

module MyModule
  def hallo
    puts "hallo"
  end
end

相当简单的设置。但是它不起作用 :( :
ruby test.rb
test.rb:8:in `<class:MyApp>': undefined method `hallo' for MyApp:Class (NoMethodError)
        from test.rb:6:in `<main>'

我的错误在哪里?
4个回答

82
简而言之:你需要使用extend来扩展模块,而不是使用include
class MyApp
  extend MyModule
  self.hallo
end

include提供了一个类的实例方法,该方法将被混入到这个类中。

extend为混入它的类提供了类方法。

阅读this


14
问题在于你在类定义中调用了 hallo,而你将其添加为实例方法 (include)。
因此,你可以使用 extendhallo 将成为一个类方法):
module MyModule
  def hallo
    puts "hallo"
  end
end

class MyApp
  extend MyModule
  self.hallo
end

或者在MyApp的实例中调用hallo:

module MyModule
  def hallo
    puts "hallo"
  end
end

class MyApp
  include MyModule
end

an_instance = MyApp.new
an_instance.hallo

9
您的代码是有效的,但包含模块并不会达到您期望的效果。包含该模块的类将不会获得该方法,而是该类的对象会获得该方法。
因此,以下代码可以正常工作:
class MyApp
  include MyModule
end

my_app_object = MyApp.new
my_app_object.hallo # => hallo

my_app_object是MyApp类的对象,该类使用了MyModule模块的混入。点击这里获取有关模块和混入的完整说明。


4
class MyApp
  class << self
    include MyModule
  end
  self.hallo
end

是相同的。
class MyApp
  extend MyModule
  self.hallo
end

extends 只是打开了类对象并包含模块方法。"hallo" 成为了 MyApp 类的类对象,也就是静态方法。

所以 "include" 将方法注入到接收者的实例中,在您的情况下是 "self",而不是对象本身。"extend" 将方法注入到接收者中,在您的情况下是 "self"。

self.include MyModule // inject the methods into the instances of self
self.extend MyModule // inject the methods into object self

在类级别上,“self”将指向您的类对象MyApp。

还要记住,“include”和“extend”只是在module.rb中定义的方法。 “include”是一个类对象方法(静态方法),而“extend”是一个实例方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接