Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
module / include / extend / mixin
Rubyのモジュール(module)とミックスイン(mixin)の仕組みです。複数のクラスに共通の機能を持たせる多重継承の代替手段として使われます。
構文
# モジュールの定義。
module モジュール名
def インスタンスメソッド
処理
end
def self.モジュール関数
処理
end
end
# include: モジュールのメソッドをインスタンスメソッドとして追加します。
class クラス名
include モジュール名
end
# extend: モジュールのメソッドをクラスメソッドとして追加します。
class クラス名
extend モジュール名
end
# prepend: include より前にメソッド探索チェーンに挿入します(メソッドの前処理に使います)。
class クラス名
prepend モジュール名
end
# 特定のオブジェクトにだけモジュールを extend します(シングルトンメソッド)。
オブジェクト.extend(モジュール名)
メソッド一覧
| 構文 / メソッド | 概要 |
|---|---|
| module モジュール名 | モジュールを定義します。インスタンス化できず、クラスと異なり継承もできません。 |
| include モジュール名 | モジュールのメソッドをクラスのインスタンスメソッドとして追加します。 |
| extend モジュール名 | モジュールのメソッドをクラスのクラスメソッドとして追加します。 |
| prepend モジュール名 | モジュールをメソッド探索チェーンの先頭に挿入します(オーバーライドの前処理に便利です)。 |
| include? / ancestors | クラスがどのモジュールをインクルードしているか確認できます。 |
サンプルコード
# 挨拶機能を提供するモジュール。
module Greetable
def greet
"こんにちは!私は#{name}です。"
end
def farewell
"さようなら!#{name}でした。"
end
end
# ログ機能を提供するモジュール。
module Loggable
def log(message)
puts "[LOG] #{self.class}: #{message}"
end
end
# include でインスタンスメソッドとして追加します。
class Person
include Greetable
include Loggable
attr_reader :name
def initialize(name)
@name = name
end
end
class Robot
include Greetable
attr_reader :name
def initialize(name)
@name = name
end
end
# モジュールのメソッドが使えます。
p = Person.new("Alice")
puts p.greet # こんにちは!私はAliceです。
puts p.farewell # さようなら!Aliceでした。
p.log("起動しました") # [LOG] Person: 起動しました
r = Robot.new("R2D2")
puts r.greet # こんにちは!私はR2D2です。
# モジュールの確認。
puts Person.ancestors.inspect
# [Person, Loggable, Greetable, Object, Kernel, BasicObject]
概要
Rubyは多重継承を持ちませんが、モジュールのミックスインによって複数のクラスに共通機能を持たせることができます。モジュールは「機能の集まり」としてクラスとは別に定義し、必要なクラスに『include』または『extend』で取り込みます。
『include』はモジュールのメソッドをインスタンスメソッドとして追加し、『extend』はクラスメソッドとして追加します。メソッド探索の順序は『ancestors』で確認できます。後からインクルードしたモジュールが探索順で前になります(スタック構造)。
モジュールはインスタンス化できません。モジュールに状態(インスタンス変数)を持たせると、インクルード先のクラスのインスタンス変数と混在するため混乱を招きます。モジュールにはなるべくステートレスなメソッドのみを定義することが推奨されます。
標準ライブラリの『Comparable』モジュールを使ったカスタム比較については『Comparable / <=>』を、継承の仕組みは『継承 / super』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。