モジュールはクラスだけでは賄えない部分を担当するものというイメージです。 モジュールはインスタンス化という事ができません。しかし、モジュールは他のモジュールやクラスにインクルードすることができます。
モジュールでは定数やメソッドを定義する事が出来ます。
モジュールはクラスだけでは賄えない部分を担当するものというイメージです。クラスは〇〇(クラス).newとすることでオブジェクトを作成、つまり〇〇クラスのインスタンスを作ることができます。これをインスタンス化と呼びます。
モジュールはこのインスタンス化という事ができません。しかし、モジュールは他のモジュールやクラスにインクルードすることができます。クラスはインクルードができません。(インクルードとは何かについてはMix-inでご説明します。)また、モジュールでは定数やメソッドを定義する事が出来ます。
モジュールを作りたいときは、以下のように書きます。
module モジュール名
定義
end
モジュール名の1文字目はアルファベット大文字でなければいけません。2文字目以降は小文字の英数が使えます。そして、例えば「FileTest」のように単語を2つ書きたいときは、単語の1文字目を大文字にします。変数などの時と異なり「_」アンダースコアで区切るのではないという事ですね。
モジュールで定義した定数を参照する際は以下のよう形で書きます。
モジュール名::定数名
モジュールの中では、メソッドを定義する事が出来ます。定義したメソッドを「モジュール名.メソッド名」という書き方で呼び出したい場合は、「module_function :メソッド名」という形でモジュール内に記述します。
module Aisatsu
def hello
puts "こんにちは"
end
module_function :hello
end
Aisatsu.hello
#こんにちは
「モジュール名.メソッド名」の形で呼び出しできていることが分かりますね!
複数人でプログラムを作っていると、メソッドやクラスの名前が重複するという事が起こってしまう可能性が出てきます。このような事が起こると、先に書いたクラスでの定義などが同じ名前で書いた定義で上書きされてしまい、エラーが出るという事になりかねません。
そういった事を回避するために名前空間というものを使います。つまり、モジュールを名前空間(衝突回避目的で)として使うというイメージです。モジュール内で書いたメソッドを参照する場合は、
モジュール名.メソッド名
という形で参照できます。
「include」というものを使いモジュールをクラスの中に取り込むことをMix-inといいます。(取り込む=include(インクルード)する。という言い方もされます。)クラスの継承と似た部分もあるので使い道などについて迷うこともあるかもしれませんが、以下ポイントを参考に使い分けると良いでしょう。
・複数のクラスが存在していて、それぞれのクラスが内容の近い機能を保持している。しかし、同じスーパークラスのサブクラスとはしたくない時。
・既にスーパークラスを定めている(継承)が、共通機能などをうまくまとめられない時。rubyでは2個以上スーパークラスを持てません。この事を、単純継承(単一継承)といいます。定めたスーパークラスで賄いきれなければMix-minを使うとよいという事ですね。
書き方については以下のようになります。
module モジュール名
共通項目(メソッドなど)
end
class クラス1(クラス名)
include モジュール名
クラス1の為のメソッドなど
end
class クラス2(クラス名)
include モジュール名
クラス2の為のメソッドなど
end
このようにインクルードする事により、モジュール内に書いたメソッドはクラス1とクラス2のインスタンスメソッドとして使用できます。では、例を使い実際にコードを書いてみましょう1。
module TestModule
def name
"山田"
end
end
class TestClass
include TestModule
end
instance = TestClass.new
p instance.name
#=> "山田"
instance = TestClass.newで、TestClassのインスタンスを作成しています。そして、p instance.nameでインスタンスに対しTestModuleのメソッドを呼び出していますね。ちなみに、インクルードされたモジュールは仮想的なスーパークラスとなります。
上記module.rbでいうとインクルードされたTestModuleはTestClassの仮想的なスーパークラスという事です。仮想的なということなので、スーパークラスではありません。あくまでも、スーパークラスのように扱われるというだけです。
クラスの継承関係は、以下メソッドを使えば調べる事が出来ます。
・ancestors
・superclass
では、実際に使うとどのような結果が出るかを、上記module.rbのTestClassで試してみましょう。
p TestClass.ancestors #=> [TestClass, TestModule, Object, Kernel, BasicObject] p TestClass.superclass #=> Object
このように、「ancestors」を使えば継承関係のクラスを全て知ることが出来ます。モジュールもスーパークラスではありませんが、仮想的なスーパークラスという事で一覧に含まれていますね。そして、「superclass」の方はモジュールは含まれず、スーパークラスであるObjectとなっています。
rubyであらかじめ用意されているEnumerableというモジュールがあります。このモジュールは、配列やハッシュなどオブジェクトの集まりのクラスで検索などを行うためのものです。自分で定義をしたクラスでこのモジュールを使いたい場合は、クラスの中でeachメソッドが使われていないといけません。
Mix-inを使用したときどのような構文かによって、メソッドの実行される順が変わります。
1.インクルード先のクラスで同名のメソッドがある時は、クラスの方のメソッドが優先されます。
module TestModule
def foo
"モジュール"
end
end
class TestClass
include TestModule
def foo
"クラス"
end
end
instance = TestClass.new
p instance.foo
#=> "クラス"
2.クラスに複数モジュールをインクルードした際は、最後に書いたモジュールが優先されます。
module Module1
def foo
"モジュール1"
end
end
module Module2
def foo
"モジュール2"
end
end
class TestClass
include Module1
include Module2
end
instance = TestClass.new
p instance.foo
#=> "モジュール2"
3.モジュールの中で他のモジュールがインクルードされている場合でも検索順は、最後に書いたもの~最初に書いたものの順です。
module Module1
:
end
module Module2
:
end
module Module3
include Module1
end
class TestClass
include Module2
include Module3
end
p TestClass.ancestors
#=> [TestClass, Module3, Module2, Module1, Object, Kernel, BasicObject]
*同じモジュールをクラス内で複数回インクルードしたとしても2回目以降は有効となりません。
includeはクラスに追加されるものですが、この「extend」はオブジェクトに機能が追加されます。追加される際は、モジュール内のメソッドが特異メソッドとなります。このメソッドを使えばモジュールで定義した機能をオブジェクトごとに使用できるのです。では、使い方を以下例で学びましょう。
module Test
def test(name)
"#{self}、#{name}です"
end
end
my_name = "私の名前は"
my_name.extend(Test)
p my_name.test("山田")
#=> "私の名前は、山田です"
my_name.extend(Test)でmy_nameにモジュールを取り込んでいます。そうすると、my_nameでtest(name)というメソッドが使えるようになります。この例では、「メソッド名(引数)」としていますが、不要であれば引数は指定しなくてもよいです。
クラスというものは、Classクラスに属するオブジェクトです。ですので、extendをクラスに対して使う事も可能となります(クラス内にextendを記述する)。
extendを使う事でモジュールに書いたメソッドはクラスメソッドとなります。したがって、以下例のように「クラス名.(モジュールで定義した)メソッド名」という形で呼び出せるようになります。
module TestModule def test "モジュール内で定義したメソッド" end end class TestClass extend TestModule end TestClass.test #=> "モジュール内で定義したメソッド"
モジュールとはメソッドや定数を入れておくことが出来るものです。しかし、インスタンス化することは出来ません。
モジュールは名前空間として使う事が出来るのです。「include」を使用しモジュールをクラスに取り込むことを「Mix-in」といいます。
無料ビデオ講座のお知らせ
Skillhub [スキルハブ]では無料の動画講座を多数公開しています。他校だと数万円するような講座が無料で受講できます。