0
0

Rubyクラスにモジュールを取り込むinclude、prepend、extendの違いと比較

Last updated at Posted at 2024-06-20

モジュールをクラスに組み込むには3つの方法があります。それは includeprepend、そして extend です。この記事では、これら3つの方法の違いと共通点を詳しく解説し、比較します。

Rubyのinclude

include は、他のモジュールからコードをクラスにインポートする最も一般的な方法です。include はモジュールのメソッドをクラスのインスタンスメソッドとして追加します。つまり、そのクラスのオブジェクトでこれらのメソッドを呼び出すことができます。

includeの例

module Greetings
  def greet
    puts "Hello world!"
  end
end

class Person
  include Greetings
end

person = Person.new
person.greet # 出力: "Hello world!"

モジュールをクラスにincludeしたときのancestors chain

モジュールをクラスに include すると、そのモジュールはそのクラスの ancestors chain に追加されます。位置はそのクラスの直後、スーパークラスの前になります。

上記の例でancestors chainを確認すると次のようになります:

Person.ancestors
# => [Person, Greetings, Object, Kernel, BasicObject]

モジュール Greetings は ancestors chain に追加され、クラス Person の直後、スーパークラス Object の前に配置されます。

複数のモジュールをincludeした場合、ancestors chainはどうなるか?

次のコード例を見てみましょう:

module Greetings
  def greet
    puts "Hello world!"
  end
end

module Working
  def work
    puts "Working..."
  end
end

class Person
  include Greetings
  include Working
end

この場合、Person.ancestors を確認すると次のようになります:

[Person, Working, Greetings, Object, Kernel, BasicObject]

後からincludeされたモジュールはクラスに近い位置に配置されます。つまり、2つのモジュールが同じメソッドを持っている場合、後からincludeされたモジュールのメソッドが優先して実行されます。これにより、includeの順序は非常に重要になります。

Rubyのprepend

prepend はRuby 2.0から導入されましたが、includeextend ほど一般的ではありません。

prepend は本質的には include と似ていますが、違いは prepend されたモジュールがancestors chainのクラスの前に追加される点です。これにより、モジュールとクラスの両方が同じメソッドを持っている場合、prepend されたモジュールのメソッドが優先されます。

prependの例

module Greetings
  def greet
    puts "Hello world!"
  end
end

module Working
  def greet
    puts "Working..."
  end
end

class Person
  prepend Greetings
  include Working

  def greet
    puts "Hi"
  end
end

person = Person.new
person.greet # 出力: "Hello world!"

この場合、Person.ancestors を確認すると次のようになります:

[Greetings, Person, Working, Object, Kernel, BasicObject]

ご覧のとおり、prepend されたモジュールは先頭に配置され、その後にクラス、include されたモジュールの順になります。

Rubyのextend

extendincludeprepend とは異なり、モジュールをクラスに extend すると、そのモジュールのメソッドがクラスメソッドとしてインポートされます。インスタンスメソッドではありません。

extend はモジュールをクラスのancestors chainに追加しません。

extendの例

module Greetings
  def greet
    "Hello world!"
  end
end

class Person
  extend Greetings
end

puts Person.greet # 出力: "Hello world!"

ここでは、モジュール Greetings がクラス Personextend され、greet メソッドが Person のクラスメソッドとなっています。

まとめ

Rubyでは、includeextendprepend の3つのメソッドを使用して、モジュールのメソッドをクラスやオブジェクトに追加します。それぞれのメソッドは異なる動作と目的を持っています。以下はこれらのメソッドの比較表です:

メソッド 説明
include * モジュールのメソッドをインスタンスメソッドとして定義する。
* クラスに同名のメソッドが既に存在する場合、クラスのメソッドが優先される。
* 後からincludeされたモジュールのメソッドが優先される。
prepend * ancestors chainの先頭にモジュールを挿入し、モジュールのメソッドをインスタンスメソッドとして定義する。
* クラスに同名のメソッドが既に存在する場合、モジュールのメソッドが優先される。
extend * モジュールのメソッドをクラスメソッドとして使用できるようにする。
* モジュールをクラスのancestors chainに追加しない。

これらのメソッドの使い方を理解することで、Rubyのプロジェクトにおいてコードをより効果的かつ柔軟に組織化することができます。ぜひ試してみて、Rubyの能力を最大限に活用してください!

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