moduleについて
モジュールの定義
モジュールの構文
module <モジュール名> # 定数やメソッドなど end # 例 module Greeter def hello 'hello' end end
クラスの構文と同じだが、以下の注意点がある。
- モジュールからインスタンスを作成できない。
- 他のモジュールやクラスを継承することはできない。
ミックスイン
include
モジュールで定義したメソッドをインスタンスメソッドとして使用することができる。
module Loggable def log(text) puts "[Log] #{text}" end end class Product # モジュールをincludeする。 include Loggable def initialize(title) @title = title end def title # logメソッドはモジュールで定義したもの。 log('name is called') @title end end product = Product.new('A great movie') product.title # => [Log] name is called # => A great movie
extend
モジュール内のメソッドをそのクラスの特異メソッド(クラスメソッド)にすることができる。
module Loggable def log(text) puts "[Log] #{text}" end end class Product # extendを使用することでクラスメソッドとしてmixinすることができる。 extend Loggable # クラス構文の直下で使用可能。(selfがクラス自身のため) log('Defined Product class') def initialize(title) @title = title end def self.create_products(names) # クラスメソッド内で呼び出すことが可能になる。 log('create_products is called') end end # クラスメソッド経由でlogメソッドが呼び出される。 Product.create_products([]) # => [Log] create_products is called # Productクラスのクラスメソッドとして直接呼び出すことも可能。 puts Product.log('hello') # => [Log] hello
モジュールに特異メソッドを定義する
mixinせずにモジュール単体でメソッドを使用したい場合に使用する。 モジュールはインスタンスオブジェクトが作れないので、newする必要がない 「単なるメソッドの集まり」を作りたいケースに向いている。
module Loggable # 特異メソッドとして定義する。 def self.log(text) puts "[LOG] #{text}" end end # クラスと同様にclass << self を使用して定義できる。 module Loggable class << self def log(text) puts "[LOG] #{text}" end end end Loggable.log('hello')
module_functionメソッド
ミックイン、モジュールの特異メソッドとして両方で使えるメソッドを定義する際に使用する。このように両方で使用できるメソッドをモジュール関数という。
module Loggable def log(text) puts "[LOG] #{text}" end # module_functionは対象のメソッドの定義よりも下で定義すること! module_function :log end Loggable.log('hello') # => [Log] hello class Product include Loggable def title log('title is called') end end product = Product.new product.title # => [Log] title is called
注意1
モジュール関数はミックスインされると自動的にprivateメソッドになる。
product = Product.new product.log('hello') # => NoMethodError
注意2
module_functionメソッドを引数なしで呼び出した場合、そこから下に定義されたメソッドが全てモジュール関数になる。
module Loggable module_function def log(text) puts "[Log] #{text}" end end
moduleに状態を保持する。
外部ライブラリでは、そのライブラリを実行するための設定値をモジュール自身に保存させることがあるらしい。
module AwesomeApi @base_url = '' @debug_mode = false # クラスインスタンス変数を読み書きするための特異メソッドを定義する。 class << self attr_accessor :base_url, :debug_mode end end AwesomeApi.base_url = 'http://example.com' AwesomeApi.debug_mode = true AwesomeApi.base_url # => http://example.com AwesomeApi.debug_mode # => true