Rubyのモジュール、ミックスインについて学ぶ
モジュール
大まかにはクラスからインスタンス生成の機能を省いたもの
モジュール定義
メソッドを共同利用したい時や、名前空間を分けたい (同名のクラスやメソッドを複数用意したい) 時に利用する
モジュールにも、「クラスメソッド」を定義できる(self.メソッド名)
モジュールをincludeすると、モジュールのメソッドを「インスタンスメソッド」として利用できる
Module#include
モジュールをextendすると、モジュールのメソッドを「クラスメソッド」(クラスが持つ特異メソッド) として利用できる
Object#extend
クラスに対して特異メソッド (クラスメソッド) を追加する以外に、特定のインスタンスに対して特異メソッドを追加するという使い方もできる
モジュールをincludeするなどして、クラスや他のモジュールに組み込むことを「ミックスイン」という
一部のオブジェクト指向言語が持つ「多重継承」の仕組みと似ている
組み込みモジュールを、独自のクラスにincludeしてメソッドを追加するという使い方もできる
Enumerable:様々な繰り返し処理を行うためのモジュール
基本となる each メソッドをincludeする側で定義しておく必要がある
Comparable:比較演算を行うためのモジュール
基本となる<=>演算子をincludeする側で定義しておく必要がある
Kernel:全てのクラスから参照可能なメソッドを提供するモジュール
Objectクラス (全てのクラスのスーパークラス) がincludeしているため、どこでも呼び出せる
Rubyのトップレベル (クラス定義やモジュール定義の外) におけるselfは、mainという名前のオブジェクト (Objectクラスのインスタンス)
selfについて学ぶ
トップレベルのselfはObjectクラスのインスタンスであり、ObjectクラスはKernelモジュールをincludeしているため、いきなりpメソッドやputsメソッドを呼び出せる
モジュール内で定義したメソッドの中で、ミックスイン先のクラスのインスタンス変数を書き換える場合は、直接インスタンス変数を使うのではなく、アクセサを使おう
元のクラスで定義されていないインスタンス変数を使ってもエラーにならないため (メソッドの場合は、定義されていなければエラーになる)
モジュール内のクラスや定数の定義または参照を行うには、モジュール名::クラス名/定数名と書く
::の左が空の場合は、トップレベルを指定したことになる
::は、メソッド呼び出しの.の代わりに使うこともできる (ただし、大文字で始まるメソッドを参照する場合は定数と区別するために()が必要)
メソッド呼び出し(super・ブロック付き・yield)
Rubyスタイルガイドを読む: 文法(1)メソッド定義、引数、多重代入|TechRacho by BPS株式会社
モジュール自身に特異メソッドを定義すると、モジュール名.メソッド名でどこでも呼び出せる
モジュールを外部ライブラリとして提供するような場合、設定値をモジュール自身のインスタンス変数として保持することで、変数の値を「唯一」にすることができる (シングルトンパターンの変形)
5. Singleton パターン | TECHSCORE(テックスコア)
本来のシングルトンパターンを実現する場合、クラスからSingletonモジュールをincludeし、instanceメソッドで唯一のインスタンスを取得するというやり方がある
Module#ancestors:クラスやモジュールが継承しているクラスとインクルードしているモジュールのリストを優先順で確認できる
モジュールをprependすると、prependされたモジュールが、prepend先のクラスやモジュールを継承する形でメソッドや定数を上書きする
Module#prepend
再定義したメソッドから元のメソッドの呼び出しを行いたい場合、aliasを使って別名で再定義するよりも、prependを使って同名のメソッドを再定義する方がわかりやすい
code:use_module.rb
module Foo
def a
'ok Foo'
end
end
module Bar
def b
'ok Bar'
end
end
class Klass
include Foo
extend Bar
end
p Klass.new.a #=> "ok Foo"
p Klass.b #=> "ok Bar"
#ゼロからわかる_Ruby_超入門
#プロを目指す人のためのRuby入門
#Rubyのオブジェクト、インスタンス、クラスについて学ぶ
#Rubyを学ぶ