Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

読書ログ『メタプログラミング Ruby 第2版』3章

More than 1 year has passed since last update.

3章 火曜日: メソッド

動的メソッド

  • メソッドを呼び出すというのは、オブジェクトにメッセージを送ること

Object#send

  • メソッドを呼び出すには、ドット記法Object#sendがある
    • obj.send(:my_method, 3)
  • Object#sendを使うと、どんなメソッドでも呼び出せてしまう
    • privateメソッドを呼び出せるからこそ、sendを使う

動的ディスパッチ

  • sendメソッドを使って、呼び出したいメソッド名を引数として、コードの実行時に呼び出すメソッドを決めること

メソッドを動的に定義する

Module#define_method

  • 実行時にメソッド名を定義できる
  • メソッド名とブロックを渡すことで、ブロックがメソッドの本体となる
class MyClass
    define_method :my_method do |my_arg|
        my_arg * 3
    end
end

obj = MyClass.new
obj.my_method(2) #=> 6

手順1: 動的ディスパッチを追加する

手順2: メソッドを動的に生成する

手順3: コードにイントロスペクションをふりかける

method_missing

  • BasicObjectクラスの、privateインスタンスメソッド

    • NoMethodErrorを返すのが役割
  • 指定したメソッドが継承チェーンを遡っても見つからない場合、Rubyは、method_missingを呼び出して負けを認める。

  • method_missingが呼び出されると

  hoge.send :method_missing, :my_method
  => NoMethodError: undefined method 'my_method' for <...>
  • method_missingをオーバーライドすると、実際には存在しないメソッドを呼び出せる
class Lawyer
  def method_missing(method, *args)
    puts "呼び出した: #{method}(#{args.join(',')})"
    puts "(ブロックも渡した)" if block_given?
  end
end

bob = Lawyer.new
bob.talk_simple('a', 'b') do
    # ブロック
end

=> 呼び出した: talk_simple(a,b)
(ブロックも渡した)

ゴーストメソッド

  • method_missingを呼び出す際、通常と同様に見えるが、レシーバ側に対応するメソッドが見当たらないこと。
    • 「君が理解できないことを頼まれたら、これをやっておいてね」という感じ

動的プロキシ

  • ゴーストメソッドを補足して、他のオブジェクトに転送するオブジェクトのこと。

respond_to_missing?

  • Rubyが、respond_to?にゴーストメソッドを認識させる仕組み
  • method_missingをオーバーライドしたときには、respond_to_missing?もオーバーライドすること。

const_missing

  • 存在しない定数を参照すると、Rubyは定数の名前をconst_missingにシンボルとして渡す。
  • クラス名は単なる定数なので、不明な参照はModule#const_missingに渡される

ブランクスレート

  • 最小限のメソッドしかない状態のクラスのこと
  • ブランクスレートが必要であれば、BasicObjectを直接継承する

まとめ

可能であれば動的メソッドを使い、仕方がなければゴーストメソッドを使う

感想

Object#sendを使って、動的にメソッドを呼び出すこと、Module#define_methodを使って、動的にメソッドを定義する、という動的メソッドの存在を知る。

また、BasicObject#method_missingを上書きし、存在しないメソッドをゴーストメソッドとして生成する方法を知る。

一旦は見た際に気づけるかな、という感覚。実際に自分で使うとなると、もう少し慣れや自信が必要かな、という肌感。:sweat:

baramatsubonzo
細々と頑張ってます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away