web-dev-qa-db-ja.com

Ruby:モジュール、requireおよびinclude

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>'

私のエラーはどこにありますか?

41
Dakkar

要するに、モジュールのextendの代わりにincludeが必要です。

class MyApp
  extend MyModule
  self.hallo
end

includeは、それを混合するクラスのインスタンスメソッドを提供します。

extendは、それを混合するクラスのクラスメソッドを提供します。

this 読み取りを行います。

67
Kyle

問題は、クラス定義でhalloを呼び出しているのに、インスタンスメソッド(include)として追加していることです。

したがって、extendを使用できます(halloはクラスメソッドになります)。

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
11
CCD

コードは機能していますが、モジュールを含めても、思ったとおりには動作しません。モジュールを含むクラスはメソッドを取得しません-このクラスのオブジェクトは取得します。

したがって、これは動作します:

class MyApp
  include MyModule
end

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

my_app_objectはクラスMyAppのオブジェクトで、モジュールMyModuleのミックスインがあります。モジュールとミックスインの完全な説明については、 there をご覧ください。

7
Martin
class MyApp
  class << self
    include MyModule
  end
  self.hallo
end

と同じです

class MyApp
  extend MyModule
  self.hallo
end

extendsはクラスオブジェクトを開き、モジュールメソッドを含めるだけです。 「ハロー」はクラスオブジェクト別名になります。クラスMyAppの静的メソッド。

したがって、メソッドをレシーバーのインスタンスに「インクルード」インジェクトします。この場合、オブジェクト自体ではなく「セルフ」です。 「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"はインスタンスメソッドです。

4
Viorel