0
0

More than 1 year has passed since last update.

Moduleの使い方について

Last updated at Posted at 2022-10-17

環境

Ruby 2.6

はじめに

モジュールの使い方は、大きく2種類に分けることができます。

  1. モジュールを単体で呼び出して使う
  2. クラスにinclude(もしくはextend)してクラスの拡張メソッドとして使う

そして、上記1の方法しか使わない場合、上記2の方法しか使わない場合、上記1,2の両方を併用して使う場合とで、メソッドの定義の仕方が変わってきます。

そんな3種類の定義の仕方をまとめてみました。

動作確認(その1)

動作確認用に、3種類のモジュールを作成しました。

test_module.rb
# 1のパターン
module Test_module1
    def self.mod_test1
        puts "#{__method__}"
    end
end

# 2のパターン
module Test_module2
    def mod_test2
        puts "#{__method__}"
    end
end

# 3のパターン
module Test_module3
    def mod_test3
        puts "#{__method__}"
    end
    module_function :mod_test3
end

モジュールを単体で呼び出して使う場合、パターン1、パターン3は問題なく動作します。

$Test_module1.mod_test1
=> mod_test1

$Test_module3.mod_test3
=> mod_test3

パターン2の場合はエラーになります。このような書き方はできません。

$Test_module2.mod_test2
=> undefined method `mod_test2' for Test_module2:Module (NoMethodError)

動作確認(その2)

上記のモジュールをクラスに取り込みました。

test_class.rb
class Test_class
    
    extend Test_module1
    extend Test_module2
    extend Test_module3

    class << self        
        def cls_cls_test1
            mod_test1
        end

        def cls_cls_test2
            mod_test2
        end

        def cls_cls_test3
            mod_test3
        end
    end
end

パターン1の場合は、クラスから呼び出して使うことはできません。呼び出そうとするとエラーになります。

$Test_class.cls_cls_test1
=> undefined local variable or method `mod_test1' for Test_class:Class (NameError)

$Test_class.mod_test1
=> undefined method `mod_test1' for Test_class:Class (NoMethodError)

パターン2の場合は問題なく動作します。

$Test_class.cls_cls_test2
=> mod_test2

$Test_class.mod_test2
=> mod_test2

パターン3の場合は、クラスの中のメソッドから、外部のモジュールを呼び出す分には問題ないが、外部のモジュールのメソッドを直接呼び出すことはできないという制限が入ります。

$Test_class.cls_cls_test3
=> mod_test3

$Test_class.mode_test3
=> private method `mod_test3' called for Test_class:Class (NoMethodError)

結論

下記のような使い分けをしましょうということになります。

  • モジュールを単体で呼び出して使うようなときでしか使わない場合は、メソッドにselfをつける。

  • クラスにinclude(もしくはextend)して、クラスの拡張メソッドとしてしか使わない場合は、selfも、module_functionもつけない。

  • モジュールを単体で呼び出して使う場とき、クラスにinclude(もしくはextend)してクラスの拡張メソッドとして使うときと、両方の使い方をする場合は、module_functionを使う。(ただし、クラス内のメソッドからしか読み込まれないという制限付き)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0