継承, mix-in, include, extend について覚え書き

継承

  • rubyでは単一継承のみ
  • 多重継承は、mix-in(後述)という概念で対応している
class SuperClass
  def super_say
    p "super_hello"
  end
end

class SubClass < SuperClass
  def sub_say
    p "sub_hello"
  end
  
  def super_say
    p "sub_super_hello"
    # 親クラスのメソッド呼び出し
    super
  end
end

subClass = SubClass.new
subClass.sub_say    # sub_hello
subClass.super_say  # sub_super_hello, super_hello

モジュール

  • 概念的には、クラスに近いが、インスタンスやサブクラスは作れない(後述するmix-inの為)
    • 実は、Class は Module の サブクラス
  • 名前空間に使うものというイメージだけど、mix-in という概念にも使える
module TestModule
  # インスタンスメソッド
  # モジュールは、インスタンスを作れないので、呼び出せない
  def say
    p "hello"
  end

  # モジュールの特異メソッド
  def self.say
    p "hello_self"
  end
end

# 特異メソッドが呼び出される
TestModule.say # hello_self

mix-in


以下の特徴を持つ抽象クラス(mix-in クラス)のみ多重継承を許可する事で、多重継承を安全に行う仕組み

include

  • Module#include
  • クラスに対象のモジュールを mix-in させる
# クラスにinclude
class IncludedClass
  include TestModule
end

includedClass = IncludedClass.new
IncludedClass.say # hello

モジュール関数

module TestModule
  def say
    p "hello"
  end
  # モジュール関数を定義
  module_function :module_func_say
end

# モジュールの特異メソッドとしても呼べる
TestModule.say # hello

class TestClass
  def saysay
    say
  end
end

# インスタンスからも呼べる
TestClass.new.saysay

extend

  • Object#extend
  • オブジェクトの特異メソッドとして、対象のオブジェクトのインスタンスメソッドを追加
  • オブジェクトの特異メソッドは、追加されない
# クラスにextend
class ExtendedClass
  extend TestModule
end
ExtendedClass.say # hello

extendedClass = ExtendedClass.new
# クラスの特異メソッド(クラスメソッド)として追加されるので、
# インスタンスには影響しない
#extendedClass.say # NoMethodError

# インスタンスにextend
extendedClass.extend TestModule
extendedClass.say # hello

mainにextend

  • mainにextendすれば、どこからでも呼び出せる
# mainの特異メソッドとして追加される
extend TestModule
say # hello