LoginSignup
1
0

More than 5 years have passed since last update.

Rubyのmixinの振る舞いを#~methodsを使って確認する

Posted at

環境

Ruby 2.4.3

準備

下のようなmoduleとclassを用意します。

main.rb
module Included
  def self.included_class_method; end

  def included_public_instance_method; end

  protected

  def included_protected_instance_method; end

  private

  def included_private_instance_method; end

  module_function

  def included_module_function; end
end

module Extended
  def self.extended_class_method; end

  def extended_public_instance_method; end

  protected

  def extended_protected_instance_method; end

  private

  def extended_private_instance_method; end

  module_function

  def extended_module_function; end
end

class A
  include Included
  extend Extended
end

テスト

インスタンスメソッド

# public
A.public_instance_methods
# => [:included_public_instance_method, :remove_instance_variable, ...]

# protected
A.protected_instance_methods
# => [:included_protected_instance_method]

# private
A.private_instance_methods
# => [:included_private_instance_method, :included_module_function, :DelegateClass, ...]

モジュール関数はprivateのインスタンスメソッドとしてincludeされるようです。
あとはまあ予想通りです。

特異メソッド

# 特異メソッド
A.singleton_methods
# => [:extended_public_instance_method, :extended_protected_instance_method]

クラスメソッド

最後にクラスメソッドです。

# public
A.public_methods
# => [:extended_public_instance_method, :new, :allocate, :superclass, :<=>, ...]
A.public_methods(false)
# => [:extended_public_instance_method, :new, :allocate, :superclass]

# protected
A.protected_methods
# => [:extended_protected_instance_method]
A.protected_methods(false)
# => [:extended_protected_instance_method]

# private
A.private_methods
# => [:extended_private_instance_method, :extended_module_function, :initialize, :inherited, :using, ...]
A.private_methods(false)
# => [:extended_private_instance_method, :extended_module_function, :initialize, :inherited]

やはりモジュール関数はextendではprivateなクラスメソッドになるようです。
また、あまり予想していなかったことですが、#new#initialize等がfalseを渡したときにも含まれます。よくよく考えてみると自明ですが、これらはClassクラスのインスタンスメソッドです。

Class.instance_methods(false)
# => [:new, :allocate, :superclass]
Class.private_instance_methods(false)
# => [:initialize, :inherited]

まとめ

  • インスタンスメソッドはアクセス修飾子はそのままにinclude or extendされる
  • クラスメソッドはinclude or extendされない
  • モジュール関数はprivateのインスタンスメソッドとしてincludeされる
  • モジュール関数はprivateのクラスメソッドとしてextendされる

補足

今回使いませんでしたが、
#methods#public_methods + #protected_methods,
#instance_methods#public_instance_methods + #protected_instance_methods

1
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
1
0