チェリー本:モジュールの理解

モジュールとクラスの違い

  • モジュールからインスタンスの作成はできない
  • 他のモジュールやクラスを継承できない

モジュールの使いどころ

モジュールの用途は下記4つが紹介されていた。以下の用途を、複数使用した場合もよくあるらしい。

  • 継承を使わずにクラスにインスタンスメソッドを追加する、もしくは上書きする
  • 複数のクラスに対して共通の特異メソッド(クラスメソッド)を追加する
  • クラス名や定数名の衝突を防ぐための名前空間を作る
  • 関数的メソッドを定義する
  • 状態を保持する

モジュールの定義

モジュール定義の構文は下記。

module モジュール名
  # モジュール定義(メソッドや定数等)
end

モジュールを利用したメソッド定義(include,extend)

『is-a』の関係が成り立っていない場合、継承は使うべきでない。そんな時に共通のメソッドを持たせたいというような時にモジュールを利用できる。モジュールでメソッドを定義する時には、includeextendを使用する。

インスタンスメソッドとして、モジュールをクラスに追加したい時は、includeでモジュールをクラスに追加する。この追加のことをミックスインという。 module.png

各クラスへのincludeは、本の中の下記図がとてもイメージしやすくて理解の助けになると感じた。 module_image.png

クラスメソッドとしてモジュールをクラスに追加したいときは、extendを使う。 また、includeの場合は、当該クラスから生成されるインスタンス全てに影響してしまうけど、特定のオブジェクトだけにメソッドを追加したいというような時には、extendを使うとインスタンスに特異メソッドとして追加できる。 extend.png

クラスとインスタンスに対してextendを用いるイメージは、多分こんな感じだと思う。 extend

名前空間の作成

モジュールを使って名前空間を設定できる。クラス名などが衝突するような時に、利用してあげると良い。 module_namespace.png

また、クラス定義やモジュール定義を保存するファイルパスは、慣習として名前空間ディレクトリ名、クラス名やモジュール名をファイル名に対応させるらしい。

関数や定数を提供するモジュール

『他のクラスに組み込まずにモジュールから直接メソッドを呼び出したい』という時には、モジュール自身に特異メソッドを定義して、モジュール名.メソッド名とすればメソッドを呼び出すことができる。

また、ミックスインとしても利用したい時には、対象のメソッドを特異メソッドとして定義した後にmodule_functionメソッドで指定してあげれば良い。 ミックスインとしてもモジュールから直接呼び出せるメソッドのことをモジュール関数と呼ぶ。使い方例は下記。

module_function.png

状態を保持するモジュール

クラスインスタンス変数を使って、モジュール自身に変数を変数を保持させることができる。インスタンスを作って何かを操作するということがないのであれば、モジュールにしておいた方がよい。理由は変な勘違いを起こさせないため。具体的にどんな時かというと、外部ライブラリ(gem)だと、ライブラリを実行するための設定値をモジュール自身に持たせたりしている。 使い方例は下記。 module_config.png