Nobody dies a virgin

映画/音楽/時々プログラミング

Rubyのextendとincludeの違い

まず特異メソッドとは

特異メソッドとは特定のオブジェクトにメソッドを差し込めるというもの。つまり、オブジェクトに依存するということだな。

レシーバ.(ドット)メソッドという形式でしか使用することができないメソッド。うん、オブジェクトにかなり依存した形式ということか。

a = [1, 2, 3]
b = [4, 5, 6]

def a.put_number
  a.each { |num| puts num }
end

これはaの配列に対しては使えるメソッドだけれども、bには使えない。これが特異メソッド。

Rubyのincludeとextendの整理

includeはrubyのクラスに機能を追加するのに対して、extendはオブジェクトに対して、機能を追加する。 つまり、Object.newしたものに個別に機能を追加するイメージなのかな。 つまり、レシーバに対して、機能を追加しているということだな。

class Weapon
  extend Gun
end

#これはこれと同じ

class Weapon
  self.extend Gun
end

#extendのレシーバのWeaponクラスに対して、機能を追加している。

ここで特徴的なのはselfというクラスメソッドの形式で追加されているということ。つまり差し込んだメソッドは全て、クラスメソッドになって差し込まれている。extendは差し込まれた先の特異メソッドになっている。今回はclassの得意メソッドなので、入れられたモジュールはWeaponにドットをつけた形式でしか適用することができない。あくまでもレシーバの特異メソッドとして、入れられるので、extendを使うといつでもクラスメソッドと覚えてしまうと痛い目に合いそうな気がしなくもない。よく似たものにpretendというものがあるけどこれは継承関係の中で、差し込んだものが差し込まれたやつよりも上に来るというもの。場合によってはオーバーライドされることがあるということだ。

備忘録(extend)

ちなみにextendしたモジュールの特異メソッドは呼び出し先では使うことができない。だって、特定のレシーバにドットをつけないと使用できないのだから、呼び出し先では違うレシーバで呼ばれているもんね。