17
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

モジュール関数の作り方

Posted at

Math のように、同じメソッドを Module の特異メソッドとしても、インスタンスメソッドとしても使えるメソッドをモジュール関数といいます。

Math.log2 2  #=> 1.0
include Math
log2 2       #=> 1.0

ActiveSupport のソースを読んでいると、いくつかの方法でモジュール関数を作っていたので、気になった2つを紹介します。

extend self

いろいろなところで使われていました。

# こんな感じで
module ActiveSupport
  module Inflector
    extend self
    ...
  end
end

インスタンスメソッドを実装して、自分自身を extend することで、特異メソッドにもしているんですね。言われてみると当たり前だけど、こういう風に extend self ってやると初めて知りました。

module A
  extend self

  def method_a
    'モジュール関数です'
  end
end

A.method_a #=> "モジュール関数です"
include A
method_a   #=> "モジュール関数です"

確かに、モジュール関数になっています。便利ですね!

module_function

こちらも、いろいろな所で使われています。

# 例えばこんな感じ
class ERB
  module Util
    ...
    def html_escape(s)
      ...
    end
    ...
    module_function :html_escape
    ...
  end
end

module_function は引数にインスタンスメソッド名を、シンボルか文字列で渡すと特異メソッドを定義するメソッドです。

module A
  def method_a
    'モジュール関数です'
  end

  module_function :method_a
end

A.method_a #=> "モジュール関数です"

また、引数を渡さないで呼び出すと、module_function の後に定義したインスタンス変数は全てモジュール関数になります。

module B
  module_function

  def method_a
    'これも'
  end
  
  def method_b
    'あれも'
  end
end

B.method_a #=> "これも"
B.method_b #=> "あれも"

これも便利ですね。

extend selfmodule_function

2つのモジュール関数の定義の仕方を紹介しましたが、この2つ若干挙動が異なります。
実際に以下のように定義して、インスタンスメソッドを実行してみると

module BySlef
  extend self

  def hello_by_self
    'Hello extend self'
  end
end

module ByModuleFunction
  def hello_by_module_function
    'Hello module_function'
  end

  module_function :hello_by_module_function
end

obj = Object.new
obj.extend(BySlef).extend(ByModuleFunction)
obj.hello_by_self             #=> "Hello extend self"
obj.hello_by_module_function  #=> NoMethodError: private method `hello_by_module_function'

module_function で定義したモジュール関数の方は、インスタンスメソッドが private になっていることが分かります。このように、module_function はインスタンスメソッドと同名の特異メソッドを定義すると同時に、そのインスタンスメソッドを private にします。

ActiveSupport では、どちらの方法も良く利用されていましたが、ここら辺で上手く使い分けをするんですかね。以上、モジュール関数の定義の仕方でした。

17
17
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
17
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?