50

我正在尝试使用 Ruby 模块(mixins)。

我有 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

4 回答 4

77

简而言之:您需要extend代替include模块。

class MyApp
  extend MyModule
  self.hallo
end

include为混合它的类提供实例方法。

extend为混合它的类提供类方法。

读一读。_

于 2013-02-26T19:58:39.667 回答
13

问题是您hallo在类定义中调用,同时将其添加为实例方法 ( include)。

因此,您可以使用extend(hallo将成为类方法):

module MyModule
  def hallo
    puts "hallo"
  end
end

class MyApp
  extend MyModule
  self.hallo
end

或者调用halloMyApp 的一个实例:

module MyModule
  def hallo
    puts "hallo"
  end
end

class MyApp
  include MyModule
end

an_instance = MyApp.new
an_instance.hallo
于 2013-02-26T20:04:06.993 回答
9

您的代码正在运行 - 但包含一个模块并没有按照您的想法执行。包含模块的类将不会获得方法 - 来自此类的对象会。

所以这将起作用:

class MyApp
  include MyModule
end

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

my_app_object 是 MyApp 类的对象,它具有模块 MyModule 的 mixins。看看那里对模块和 mixin 的完整解释。

于 2013-02-26T19:54:56.220 回答
5
class MyApp
  class << self
    include MyModule
  end
  self.hallo
end

是相同的

class MyApp
  extend MyModule
  self.hallo
end

extends 只是打开类对象并包含模块方法。“你好”又变成了一个类对象。MyApp 类的静态方法。

因此,“包含”将方法注入到接收器的实例中,在您的情况下是“自我”而不是对象本身。在您的情况下,“扩展”将方法注入接收器是“自我”。

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”是一个实例方法。

于 2014-02-08T07:26:02.827 回答