Rubyのモジュール、ミックスインについて学ぶ
大まかにはクラスからインスタンス生成の機能を省いたもの
メソッドを共同利用したい時や、名前空間を分けたい (同名のクラスやメソッドを複数用意したい) 時に利用する
モジュールにも、「クラスメソッド」を定義できる(self.メソッド名)
モジュールをincludeすると、モジュールのメソッドを「インスタンスメソッド」として利用できる
モジュールをextendすると、モジュールのメソッドを「クラスメソッド」(クラスが持つ特異メソッド) として利用できる
クラスに対して特異メソッド (クラスメソッド) を追加する以外に、特定のインスタンスに対して特異メソッドを追加するという使い方もできる
モジュールをincludeするなどして、クラスや他のモジュールに組み込むことを「ミックスイン」という
一部のオブジェクト指向言語が持つ「多重継承」の仕組みと似ている 組み込みモジュールを、独自のクラスにincludeしてメソッドを追加するという使い方もできる
基本となる each メソッドをincludeする側で定義しておく必要がある
基本となる<=>演算子をincludeする側で定義しておく必要がある
Kernel:全てのクラスから参照可能なメソッドを提供するモジュール Objectクラス (全てのクラスのスーパークラス) がincludeしているため、どこでも呼び出せる
Rubyのトップレベル (クラス定義やモジュール定義の外) におけるselfは、mainという名前のオブジェクト (Objectクラスのインスタンス) トップレベルのselfはObjectクラスのインスタンスであり、ObjectクラスはKernelモジュールをincludeしているため、いきなりpメソッドやputsメソッドを呼び出せる
モジュール内で定義したメソッドの中で、ミックスイン先のクラスのインスタンス変数を書き換える場合は、直接インスタンス変数を使うのではなく、アクセサを使おう
元のクラスで定義されていないインスタンス変数を使ってもエラーにならないため (メソッドの場合は、定義されていなければエラーになる)
モジュール内のクラスや定数の定義または参照を行うには、モジュール名::クラス名/定数名と書く
::の左が空の場合は、トップレベルを指定したことになる
::は、メソッド呼び出しの.の代わりに使うこともできる (ただし、大文字で始まるメソッドを参照する場合は定数と区別するために()が必要)
モジュール自身に特異メソッドを定義すると、モジュール名.メソッド名でどこでも呼び出せる
モジュールを外部ライブラリとして提供するような場合、設定値をモジュール自身のインスタンス変数として保持することで、変数の値を「唯一」にすることができる (シングルトンパターンの変形)
本来のシングルトンパターンを実現する場合、クラスからSingletonモジュールをincludeし、instanceメソッドで唯一のインスタンスを取得するというやり方がある モジュールをprependすると、prependされたモジュールが、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"