0Pricing
Ruby Academy · レッスン

prepend とメソッド探索

祖先チェーンを学びます。

「prepend とメソッド探索」はCoddyKit上の無料Ruby Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはRuby Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Ruby Academyコースには全4レッスンが含まれています。

祖先チェーン

メソッドを呼び出すと、Rubyは祖先チェーンと呼ばれるリストを検索します。最初に見つかった一致する定義が使われます。このチェーンを理解すると、ミックスインと継承がどのように連携するかが分かります。

class Animal; end
class Dog < Animal; end
p Dog.ancestors

メソッドの探索順序

Rubyはまずオブジェクトのクラスを検索し、次にそのクラスにインクルードされたモジュール、さらにスーパークラスという順に、メソッドが見つかるまでチェーンをたどって検索します。

module M
  def hello; "from module"; end
end
class C
  include M
  def hello; "from class"; end
end
puts C.new.hello

include はクラスの下に入る

includeされたモジュールは、チェーン内でクラスのすぐ下に置かれます。クラス自身のメソッドがモジュールのメソッドより優先されます。

module M; end
class C
  include M
end
p C.ancestors  # [C, M, Object, ...]

prepend の登場

prependは、チェーン内でモジュールをクラスの上に挿入します。これにより、クラス自身のメソッドよりも前に、モジュールのメソッドが先に見つかります。

module M
  def hello; "from module"; end
end
class C
  prepend M
  def hello; "from class"; end
end
puts C.new.hello

チェーン内の prepend

祖先を調べて、prependによってモジュールがクラスの前に置かれていることを確認しましょう。

module M; end
class C
  prepend M
end
p C.ancestors  # [M, C, Object, ...]

prepend したモジュールからの super

prependされたモジュールは先に実行されるため、superを呼び出して元のメソッドに到達し、クラスのメソッドをラップできます。動作の装飾に最適な方法です。

module Logged
  def save
    puts "before save"
    result = super
    puts "after save"
    result
  end
end
class Record
  prepend Logged
  def save
    puts "saving record"
    :ok
  end
end
p Record.new.save

ミックスインでの super

superは祖先チェーンに従います。インクルードされたモジュールから呼び出すとスーパークラスに到達し、prependされたモジュールから呼び出すとクラス自体に到達します。

module Polite
  def greet; "Hi! " + super; end
end
class Person
  prepend Polite
  def greet; "I am here."; end
end
puts Person.new.greet

編集せずにラップする

prependを使うと、元のクラスのコードを変更せずに既存のメソッドの前後へ動作を追加できます。モンキーパッチの、より明確な代替手段です。

module Timing
  def compute(n)
    puts "start"
    super
  end
end
class Calc
  prepend Timing
  def compute(n); n * n; end
end
puts Calc.new.compute(5)

複数モジュールの順序

複数のモジュールをインクルードした場合、最後にインクルードしたモジュールがクラスに最も近い位置に置かれ、最初に検索されます。

module A; def who; "A"; end; end
module B; def who; "B"; end; end
class C
  include A
  include B
end
puts C.new.who  # B wins (included last)
p C.ancestors

include と prepend のまとめ

並べて比較すると、次のようになります。

  • include M:チェーンは[Class, M, ...]となり、クラスのメソッドが優先されます。
  • prepend M:チェーンは[M, Class, ...]となり、モジュールのメソッドが優先され、クラスへsuperできます。
module M; end
class Inc; include M; end
class Pre; prepend M; end
p Inc.ancestors
p Pre.ancestors

まとめ

メソッドの解決は祖先チェーンに従います。

  • クラスのメソッドは、インクルードされたモジュールより優先されます。
  • prependされたモジュールは、クラスより優先されます。
  • superはチェーンを1つ上にたどります。
module Cap
  def name; super.capitalize; end
end
class User
  prepend Cap
  def name; "ada"; end
end
puts User.new.name

確認

メソッドの解決についての理解度を確認しましょう。

振り返り

メソッドの解決について学びました。

  • Rubyは祖先チェーンを上から下へ検索します。
  • includeはクラスの下に入り、prependはクラスの上に入ります。
  • superはチェーンを上にたどり、次の定義に到達します。
  • prependを使うと、メソッドをきれいにラップできます。
module Loud
  def speak; super.upcase; end
end
class Bot
  prepend Loud
  def speak; "beep"; end
end
puts Bot.new.speak

よくある質問

「prepend とメソッド探索」レッスンは無料ですか?

はい。「prepend とメソッド探索」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Ruby Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Ruby Academyコースには全4レッスンが含まれています。

「prepend とメソッド探索」で何を学びますか?

祖先チェーンを学びます。 ブラウザで直接実行するハンズオンコードでRuby Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Ruby Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのRuby Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「prepend とメソッド探索」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このRuby Academyレッスンでコードを書いて実行できますか?

はい。すべてのRuby Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. モジュールの定義
  2. include と extend
  3. Comparable と Enumerable
  4. prepend とメソッド探索
← Ruby Academyに戻る