
今回はRubyのモジュールのミックスインについて学習していくよ!
こんな方におすすめ
- Rubyを学習している人
- モジュールを理解したい人
現場でRubyを使って開発しているので、個人の勉強記録として残します。
目次
「モジュール」とは?
一言で表すと「便利な機能をまとめたもので、クラスに機能を追加する仕組み」です。
もう少し詳しく言うと
- 継承を使わないで、クラスに機能を追加する
- 複数のクラスに対して、クラスメソッドを追加する
などです。
他にも「名前空間」として使う場合もありますが、今回は上記について解説していきます!
※名前空間に関して知りたい方は、こちらで解説していますので見てみてください。
【Ruby】名前空間とは?モジュールを使った簡単な使い方を解説!
「モジュール」の定義方法
module モジュール名
モジュール定義
end
◎例
module MusicPlayer
def play_music(song)
puts "Now playing: #{song}"
end
end
「モジュール」と「クラス」の違い
クラスはインスタンスを作成できますが、モジュールからインスタンスは作成できません。
my_mysic_player = MusicPlayer.new ❌️
クラスは継承できますが、モジュールは他のモジュールやクラスを継承することはできません。
module MusicPlayer < Player ❌️
「モジュール」のミックスイン
ミックスインとはモジュールを使ってクラスに機能を追加することを指します。
Rubyでは、クラスは1つの親クラスしか継承できず、さらに継承はs-a(〜は〜である)という関係が成り立つ場合に限られます。
しかし、実際の開発では「特定の機能を複数のクラスで共有したい」という場面がよくあり、そんなときに便利なのがモジュールになります。
モジュールを使うことで、複数のクラスに共通の機能を柔軟に追加できます。
これにより、多重継承のような柔軟性を持ちながら、シンプルで再利用しやすいコードを書くことができます。
◎例
音楽プレイヤーの機能を例に考えてみます!
module MusicPlayer
def play_music(song)
puts "Now playing: #{song}"
end
end
この「音楽プレイヤー」の機能は、「車」や「パソコン」など、さまざまな場所で使われますよね。
しかし、ここで問題があります。
- 「車」と「音楽プレイヤー」の間には is-a(〜は〜である)関係は成り立ちません。つまり、「車は音楽プレイヤーである」とは言えないため、継承は適切ではありません。
- また、Rubyではクラスは1つの親クラスしか継承できないため、「車クラス」や「パソコンクラス」の親クラスに音楽プレイヤー機能を持つクラスが存在しないと、機能を追加することができません。
このような状況では、モジュールのミックスインがとても役立ちます。
ミックスインのサンプルコード
class Car
include MusicPlayer
end
class Computer
include MusicPlayer
end
car = Car.new
car.play_music("車で音楽流しちゃう!")
# => Now playing: 車で音楽流しちゃう!
computer = Computer.new
computer.play_music("パソコンで音楽流しちゃう!")
# => Now playing: パソコンで音楽流しちゃう!
このように、「車」や「パソコン」でも共通の機能である「音楽プレイヤー」を、モジュールを使って簡単に追加できます。
「include」と「extend」
- インスタンスメソッドとして追加したい場合は、「include」を使う
- クラスメソッドとして追加したい場合は、「extend」を使う
◎includeを使ったサンプル
class Car
include MusicPlayer
end
class Computer
include MusicPlayer
end
car = Car.new
car.play_music("車で音楽流しちゃう!")
# => Now playing: 車で音楽流しちゃう!
computer = Computer.new
computer.play_music("パソコンで音楽流しちゃう!")
# => Now playing: パソコンで音楽流しちゃう!
インスタンスに対して、音楽プレイヤーを呼び出しています。
◎extendを使ったサンプル
module MusicPlayer
def play_music(song)
puts "Now playing: #{song}"
end
end
class Car
extend MusicPlayer # クラスメソッドとして追加
end
class Computer
extend MusicPlayer # クラスメソッドとして追加
end
Car.play_music("車で音楽流しちゃう!")
# => Now playing: 車で音楽流しちゃう!
Computer.play_music("パソコンで音楽流しちゃう!")
# => Now playing: パソコンで音楽流しちゃう!
インスタンスを作成せずに、直接音楽プレイヤーを呼び出しています。
インスタンスメソッド、クラスメソッドの使い分け
「音楽プレイヤー」のように、個々のオブジェクトに依存する機能は、インスタンスメソッドとして追加したほうが良さそうですね!
例えば、車ごとに異なる曲を再生したり、音量や再生リストなどを個別に管理する場合です。
一方で、クラスメソッドとして追加するのが適しているのは、サポートされているフォーマット一覧(例: MP3, WAV, AAC)のように、インスタンスごとに変わらない共通の情報を扱う場合です。
このような情報は、個々のインスタンスに関係なくクラス自体に関連するため、クラスメソッドで提供するのが良さそうです!
おわりに
今回はモジュールのミックスインについて学習してみました。
少しでも学習のお役に立てれば幸いです。
参考記事
書籍:プロを目指す人のためのRuby入門