rubyのmoduleについて

今回はrubymoduleについて説明していこうと思います。 この記事を書こうと思った経緯としては、業務においてソースコードを読んでいる時にmoduleという単語が出てきたのでJavaScriptユーザーの自分としては何ぞや?となったからです。

moduleの役割としては以下になります。

  • 定数やメソッドを定義

  • mix-inを可能とする

  • 名前空間を提供

定数やメソッドを定義

module Ziro
  Garlic = "にんにく"
  Noodles = "ふとめん"
  BeanSprou = "もやし"
  PigBones = "豚骨"
end

class Ramen
 include Ziro
 puts Garlic
end

結果はにんにくと出力されます。 注意点としては、定数は大文字から始めなくてはなりません。

mix-inを可能とする

rubyはクラス一つにつき一つしかクラスを継承することができないようです。 しかしmoduleを使うことで別のクラスとは別にメソッドや変数を継承することができます。具体的にはコードをみていきましょう。

module Cat
  def bark
    puts "ニャンニャン"
  end
end

class Zoo
  include Cat
end

zoo = Zoo.new
zoo.bark

ここで注目するのはincludeです。クラスの中でincludeと書くことでそのmoduleのメソッドはインスタンスメソッドとなります。 では猫だけだと寂しいので犬も仲間に入れてあげましょうか。

module Cat 
  def bark
    puts "ニャンニャン"
  end 
end

module Dog 
  def bark
    puts "わんわん"
  end 
end

class Zoo 
  include Dog 
  include Cat 
end

zoo = Zoo.new
zoo.bark

この結果どうなると思いますか? 結果はにゃんにゃん出力されます! Zooクラスの方で後にincludeされたmoduleが優先されます!

一方でこちらのコードも見てみましょう。

module Cat
  def bark
    puts "ニャンニャン"
  end
end

class Zoo
  extend Cat
end

Zoo.bark

includeをextendと変更しました。こうすることでインスタンスを作らなくてもクラスメソッドとして扱うことができます。ここでインスタンスを作ってからbarkを呼び出そうとしてもエラーになります。

名前空間を提供

名前空間とは、名前の衝突を避けるための概念になります。複数人で開発をしていると他の人が作成したメソッドの名前と被ってしまう可能性があります。このmoduleの中の◯◯のメソッドのように名前空間をつくることで重複を防ぎます。実際にコードを見て見ましょう。

module Animal
  class Dog 
    def self.bark
      puts "わんわん"  
    end 
  end 
end

Animal::Dog.bark #=> わんわん

このようにモジュール名::クラス名.メソッド名名前空間を作成し、メソッドを実行できることができます。

もう一階層モジュールの名前空間を深くしてみましょう。

module Creature
  module Animal
    class Dog
      def self.bark
        puts "わんわん"
      end
    end
  end
end

Creature::Animal::Dog.bark #=> わんわん

結果わんわんと出力されます。 moduleを呼び出す際には::を忘れないようにしましょう!

簡単ではありますが以上になります。