Ruby モジュール入門


Ruby モジュール入門

Rubyの機能であるモジュールですが、Rubyを始めた方にとって理解が難しい部分の一つではないかと感じています。

そこで今回はモジュールについてまとめていこうと思います。

モジュールの機能

● ミックスイン( includeとextend )
● 名前空間の作成
● 関数やメソッドを提供する

他にも機能はありますが、3つ主要な機能を挙げてみました。
今日はこれらについてみていきたいと思います。

ミックスイン

ミックスインと言われてもなんのことだかわからないと思いますが、
モジュールをクラスに組み込むことで多重継承を行えるようになります。
Rubyではclassの単一継承しかできませんが、moduleは多重継承が可能です。
またclassと違いis-aの関係(あるオブジェクトが「あるクラスもしくはその子孫クラスのインスタンスである」という関係)でなくても同じ機能を共有できます。

追記:is-aの関係の説明について修正いたしました。コメントをいただきありがとうございます。

include

ruby.rb
module Hoge
  def hello
    puts 'Hello'
  end
end

module Bar
  def bye
    puts 'Bye'
  end
end

class Greet
  #上で作ったモジュールをinclude
  include Hoge
  include Bar
end

greet = Greet.new
greet.hello #=> "Hello"
greet.bye   #=> "Bye"

以上のようにincludeすることでクラスはモジュールで定義されたメソッドを使えるようになります。
このようにモジュールをクラスにincludeして機能を追加することをミックスインといいます。

extend

extendを使うとモジュール内のメソッドをクラスメソッドにすることができます。

ruby.rb
module Hoge
  def hello
    puts 'Hello'
  end
end

class Greet
  #上で作ったモジュールをextend
  extend Hoge
end

#クラスメソッドとしてhelloを呼び出せる
Greet.hello #=> "Hello"

こんな感じでincludeやextendでモジュールで定義したメソッドをクラス内で使えるのが、
モジュールの使い方の一つであるミックスインです。

名前空間を提供する

モジュール名の中にクラスを書くとモジュールに属するクラスという意味になり
名前の衝突を防ぐことができます。

module Bar
  class Baz
    def self.foo
      puts 'foo'
    end
  end
end

#Barというモジュールに属するBazクラスよりfooメソッドを呼び出した。
Bar::Baz.foo #=> "foo"

エンジニアとして働いてから感じたことですが、
名前空間ってかなり使う機会が多いんですよね。
というのもプロジェクトが大きくなればなるほど名前の衝突が起こる危険性があるので
こうして名前空間を設定して衝突を防ぐということを頻繁に行っています。

関数やメソッドを定義する

定数

モジュール内で定義した定数は、モジュール名を経由して呼び出すことが可能。

ruby.rb
module Hoge
  Year = "2020"
end

Hoge::Year #=> "2020"

メソッド

インスタンスメソッドはmodule_functionメソッドを使って、メソッドをモジュール関数にすることで呼び出すことができるようになります。

ruby.rb
module Hoge
  def hello
    puts 'Hello'
  end

  module_function :hello
end

Hoge.hello #=> "Hello"

モジュールのまとめは以上になります。
本日で100日後に一人前になるエンジニアの連載10日目でした。

1人前のエンジニアになるまであと90日