4月生募集中!当社人気の転職保証コース
プログラミング学習から転職成功まで導く、当社人気のDMM WEBCAMP(旧WEBCAMP PRO)。
3月生は満員となっております。4月生募集に向け、お早めの申込みをオススメします。
プログラミング未経験でもエンジニア転職を絶対成功させたい
スキルを身に着けて人生を自ら切り開きたい
上記にあてはまる方は、ぜひご検討ください!

Rubyには、クラスとは別にモジュールという概念があります。

変数やメソッドをひとかたまりに管理するものですので、機能的なところだけを見るとクラスと同じように見えます。

しかし、存在している限りはその理由が必ずあるものです。

ここで、モジュールを実現しているmoduleクラスについて説明し、その存在意義や使いどころを解説していきます。

なお、本記事は「【Ruby入門説明書】リファレンス、includeについて解説」ととても関わりが深くなっていますので、合わせて読んでおいていただけると理解しやすいと思います。

Rubyのmoduleとは

他のプログラム言語でモジュールというと、関数(メソッドのようなもの)をひとまとめにして、再利用しやすくしたものです。

しかし、Rubyのモジュールは少し違っています。

もちろん、メソッドや定数を再利用しやすくするという意味では同じものです。

しかし、Rubyのモジュールは、ただ「便利ツールのかたまり」というだけではなく、よりオブジェクト指向プログラミングにあった形で使えるようになっているのです。

つまり、他のプログラム言語のモジュールを拡張した、よりプログラムの可読性や汎用性をあげるしくみだと言えるでしょう。

moduleに変数やメソッドをまとめる

では、moduleクラスの構文と使い方を説明しましょう。

moduleクラスで、変数やメソッド、クラスをひとまとめにするには、以下のように記載します。

module モジュール名
  各種定義
end

「各種定義」の部分には、「変数の定義」や「メソッドの定義」だけではなく、「クラスの定義」を記述することも可能です。

それぞれの定義について、少しだけ詳しく説明しましょう。

変数の定義とアクセス

moduleの定義でも、通常のクラスと同じく「ローカル変数」「インスタンス変数」「クラス変数」「クラスインスタンス変数」を定義することができます。

もちろん、「クラス変数」や「クラスインスタンス変数」という名称だけで、モジュールはモジュールですので、「モジュール変数」や「モジュールインスタンス変数」と呼んだ方が良いかもしれません。

具体的な例を見ていただきましょう。

module Mod_test
  C_name = "Constance"         # 定数
  l_name = "local"             # ローカル変数
  @ci_name = "@class instance" # クラスインスタンス変数
  @@c_name = "@@class"         # クラス変数
  
  def self.c_names
    @i_name = "@instance"
    p C_name
    p @i_name
    p @ci_name
    p @@c_name
  end

  def i_names
    @i_name = "@instance"
    p C_name
    p @i_name
    p @ci_name
    p @@c_name
  end

end

# インスタンス生成用
class Mod_test_class
  include Mod_test  # モジュールをクラスに取り込む
end

p("定数を直接参照")
p(Mod_test::C_name)
puts
p("モジュール経由でアクセス")
Mod_test.c_names
puts
p("インスタンス経由でアクセス")
Mod_test_class.new.i_names
puts

(結果)

"定数を直接参照"
"Constance"

"モジュール経由でアクセス"
"Constance"
"@instance"
"@class instance"
"@@class"

"インスタンス経由でアクセス"
"Constance"
"@instance"
nil
"@@class"

少し長くなっていますが、大きく分けて「定数のアクセス」「モジュール(クラスメソッド)経由のアクセス」「インスタンス経由のアクセス」の3種類のアクセス結果です。
※Mod_test_classクラスにある「include」は、モジュールをクラスに取り込む式です。詳細は「【Ruby入門説明書】リファレンス、includeについて解説」をご参照ください。

結果の通り、アクセス方法は、クラスに定義した変数と同じ方法になっています。なお、インスタンス経由のクラスインスタンス変数が「nil」になっているのは、未定義のインスタンス変数にアクセスしたと解釈されているからです。

種別 アクセス範囲 モジュール外からのアクセス
定数 制限なし 直接アクセス可能
モジュール名::定数名
インスタンス変数 モジュール内 メソッド経由
クラス変数 モジュール内 メソッド経由
クラスインスタンス変数 モジュール内(インスタントメソッド以外) クラスメソッド経由

コツコツ独学×スクールで実践。未経験からエンジニアに転職!【WebCamp卒業生インタビュー】

メソッドの定義とアクセス

変数と同じく、メソッドについてもクラスと同じ種類のメソッド(「インスタンスメソッド」と「クラスメソッド」)を定義することができます。

module Mod_test
  # インスタンスメソッド
  def i_method
    puts("instance_method")
  end

  # クラスメソッド
  def self.c_method
    puts("class_method")
  end
end

# インスタンス生成用
class Mod_test_class
  include Mod_test  # モジュールをクラスに取り込む
end

Mod_test_class.new.i_method
# Mod_test_class.new.c_method  # エラー

# Mod_test.i_method  # エラー
Mod_test.c_method

(結果)

class_method
instance_method

このように、インスタンスメソッドはモジュール経由でのアクセスはできませんが、クラスに取り込んでインスタンス経由でアクセスできます。クラスメソッドは、その逆です。

ただし、インスタンスメソッドについては、「module_functionメソッド」を使って「モジュール関数」の設定を行うことで、インスタンスがなくてもアクセスできるようにすることもできます。

module_function :インスタントメソッド名
module Mod_test
  # インスタンスメソッド
  def i_method
    puts("instance_method")
  end

  # クラスメソッド
  def self.c_method
    puts("class_method")
  end

  module_function :i_method  # モジュール関数に設定する
end

# インスタンス生成用
class Mod_test_class
  include Mod_test  # モジュールをクラスに取り込む
end

# Mod_test_class.new.i_method  # エラー
# Mod_test_class.new.c_method  # エラー

Mod_test.i_method
Mod_test.c_method

(結果)

instance_method
class_method

このように、「module_functionメソッド」でモジュール関数の設定を行うことで、インスタンスメソッドをクラスメソッドと同じように振る舞わせることができます。

「module_functionメソッド」は引数なしにすれば、以降のメソッドをすべてモジュール関数にしてくれます。そのため、クラスメソッドを複数作りたい場合、「module_functionメソッド」を使うことで、メソッド名にわざわざselfを付ける必要がなくなりますので、プログラムコードがすっきりします。

ただし、モジュール関数は自動的にprivateに設定されますので、インスタンスメソッドとしては利用できなくなりますので、注意が必要です。

もし、クラスメソッドとインスタンスメソッドの両方の使い方ができるようなメソッドを作りたければ、「extend self」を使わなければいけません。(「【Ruby入門説明書】リファレンス、includeについて解説」をご参照ください)

クラスの定義とアクセス

module内にクラスを定義する方法に、特異な部分はありません。ただし、module内のクラスへアクセスする場合は、次のような構文になりますので、注意が必要です。

モジュール名::クラス名
module Mod_test
  class Class_in_mod
    def self.test
      puts 'test_test'
    end
  end
end

Mod_test::Class_in_mod.test

“未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー

moduleの活用方法

ここからは、moduleの活用方法を紹介します。

moduleの活用方法は、大きく分けて次の3つがあります。

・クラスに取り込む
・モジュール関数のセットを作る
・同じ名前のメソッドの衝突を防ぐ

クラスに取り込む

まず、moduleのもっとも基本的な使用方法が、この「クラスにモジュールを取り込む」方法です。

「includeメソッド」や「extendメソッド」を利用して、クラスにメソッドを取り込み、クラスを機能強化するわけです。

もちろん、「クラスの継承」を行うことで、他クラスの機能を受け継ぐことはできますが、「クラスの継承」では1つしか継承できません。しかし、モジュールはいくつでも取り込めますので、moduleを使えば、他のプログラム言語で言うところの「多重継承」をRubyでも実現できるわけです。

この、moduleによる多重継承のことを、Rubyでは「Mix-in」と呼んでいます。

なお、「Mix-in」については、「【Ruby入門説明書】リファレンス、includeについて解説」で詳しく解説していますので、そちらをご参照ください

モジュール関数のセットを作る

他のプログラム言語での一般的なモジュールの使い方と同じもので、どこのクラスにも属さないような便利処理をモジュール関数としてまとめて提供するものです。

数学計算や配列処理などの汎用的な処理が該当し、実際に、Mathクラスなどで使われています。また、定数をまとめてモジュールとすることで、プログラム内での定数の定義箇所をまとめ、メンテナンス性を高めることもできます。

module00-1.rb

# 定数定義
module Const_set
  PATH = "C:\\xxx\\xxx"
  FILENAME = "xxx.xxx"
  COLOR_RED = 15
  COLOR_BLUE = 16
end

# 計算処理
module Math_test
  module_function
  def plus(a,b); a + b; end
  def minus(a,b); a -b; end
end

  puts(Const_set::PATH)
  puts(Math_test.plus(Const_set::COLOR_RED,3))

同じ名前のメソッドの衝突を防ぐ

Rubyは多数の雄志がインターネット上に数多くのプログラムを公開しています。その中には、ある機能を容易に実現できるライブラリのようなものも多く、それらを活用することで短期間で高機能な処理を実現することも可能になっています。

しかし、そういったライブラリには、自分が作ったクラスやメソッド、定数と同じ名前のものがないとも言えません。

もし、同じ名前のクラスやメソッド、定数があった場合、使用する場所によっては、どちらが利用されるのか不定になり、解析が非常に難しいバグの原因になってしまいます。

そのため、多くのライブラリ的な公開プログラムでは、「名前空間」という考え方を取り入れています。

「名前空間」というのは、ライブラリ全体を1つの「名前」で取り囲み、その名前を経由してアクセスしなければ、内部にアクセスできないようにするというものです。

必ず「名前空間の名前 + クラス(メソッドや定数)名」となるため、同じ名前のクラスやメソッドがあっても、必ず一意に決めることができるわけです。

この「名前空間」に、moduleが活用できます。

module00-1.rbに追記して、確認してみましょう。

module00-2.rb

# 定数定義
module Const_set
  PATH = "C:\\xxx\\xxx"
  FILENAME = "xxx.xxx"
  COLOR_RED = 15
  COLOR_BLUE = 16
end

# 計算処理
module Math_test
  module_function
  def plus(a,b); a + b; end
  def minus(a,b); a -b; end
end


PATH = "D:\\ooo\\ooo"
FILENAME = "ooo.ooo"
COLOR_RED = 1
COLOR_BLUE = 2

def plus(a, b)
  a + b + b
end

  puts(Const_set::PATH)
  puts(Math_test.plus(Const_set::COLOR_RED,3))

  puts(PATH)
  puts(plus(Const_set::COLOR_RED,3))

(結果)

C:\xxx\xxx
18
D:\ooo\ooo
21

なお、前述の「モジュール関数のセットを作る」というのは、「名前空間」と同じ意味とも言えます。

時間や場所にとらわれず自由に働くために必要なスキルとは?【WebCamp卒業生インタビュー】

クラスとモジュールは何が違うの?

Rubyのモジュールについての説明をしてきましたが、ここまでの説明の中で、「クラスメソッド」や「クラス変数」「クラスインスタンス変数」という言葉が出てきました。

また、アクセス方法やアクセス制限などは、クラスと同様になっています。そのため、モジュールとクラスが同じように感じている人や、混乱している人もいるかもしれません。

そこで、最後にクラスとモジュールの違いについてまとめておきましょう。

まず、明らかな違いは次の2点です。

クラス モジュール
インスタンス 作れる 作れない
継承 できる できない
簡易的なクラスメソッド記述(selfなし) できない できる

以上から、モジュールを使うべき基本的な指針が見えてきます。

つまり、モジュールを使うべき使いどころは、次のような場合でしょう。

・インスタンスを作るまでもなく使える処理を提供する
・関連する処理をひとまとめに扱って、プログラムを作る上で、利便性や安全性を高める

モジュールはプログラムの動作や処理、という実態ではなく、プログラミングしたり解析したりするために使用するしくみということです。

まとめ

Rubyのモジュールは、文法的にはクラスとほぼ同じものです。しかし、モジュールはプログラムの動作や処理そのものを実現するための手段として使うものではありません。

モジュールを使うことによって、Rubyでの開発の利便性や安全性をあげるために使うしくみなのです。
※そういう視点で見れば、moduleかインスタンスを作れず、継承できない理由は明白ですね

その辺りを理解せず、ただ同じような文法だから、ほぼ同じものだと考えるのは、後々大きな不具合を発生させますので、気を付けなければいけません。

プログラム言語に規定されているものは、すべてその目的があります。

せっかく時間をとって学習するのですから、その目的を理解して、最適な使い方ができるように、理解を深めていきましょう。

・モジュールを使えば、定数やメソッド、クラスをひとまとめにして扱いやすくできる
・モジュールを使えば、クラスの多重継承をほぼ実現できる
・moduleはインスタンスを作れない
・moduleは継承できない
・外部提供するライブラリなどは、必ずmoduleを使った名前空間を作って、メソッド名や定数名などの衝突を防ぐ
・モジュールは開発作業の負担を減らすためのしくみ

DMM WEBCAMP ONLINE/プログラミングコースについて

WEBCAMPでは、「どこでも学べる」オンラインコースを開講しています。

初心者・未経験の方でもわずか1ヶ月でプログラミングの基礎を学び、アプリケーション開発をすることができます。

DMM WEBCAMP ONLINEが選ばれる3つの理由

1.学習の仕方がわからなくても安心!初心者に寄り添った学習カリキュラム

これから学習を始める初心者の方や、独学で挫折してしまった方に向けて、アプリケーション作成をゴールとする一気通貫したカリキュラムを提供しています。2500名を輩出しているWebCampだからこその教室でのリアルな受講生の声を反映し、オンラインコースでも初心者に寄り添った学習体験をご提供いたします。

2.つまずいたらすぐ解決!プロのエンジニアに質問し放題

プログラミング学習で挫折する理由の多くは「つまずいた時に聞ける人がいない」ことです。オンラインコースでは、現役エンジニアやプロ講師に、すぐにチャットでの質問が可能です。つまずきをすぐに解消できるので、挫折せずに学習を継続することができます

3.1ヶ月間で終わらなくても大丈夫!カリキュラムは"卒業後"も"無料"で利用可能

受講したいけど、仕事が急に忙しくなるかもしれないから受講するか迷っている・・・そんな方も多いのではないでしょうか?ご安心ください。カリキュラムは期間終了後も「無料」で使うことができます。また、しっかり学習時間を確保した方も、振り返って学習することでプログラミングスキルがご自身に馴染んできます。

▼まずは無料でWEBデザインのカリキュラムを体験しよう!

【インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!

ブラジルから帰国し技術をつけようとRubyエンジニアを目指してWebCampでRubyを学び、見事Webエンジニアとして転職を果たした田中さんにお話を伺いました。

Rubyの学習がしたい。基礎をしっかりと理解したい

転職のサポートがほしい

と考えている方はぜひお読み下さい。

【WebCamp卒業生インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!

おすすめの記事