メタプログラミングRubyを読んでいます(8)

読んだ範囲

メタプログラミングRuby」の「6.1 週末を迎えるためのコーディング」から「6.3 クイズ:アトリビュートのチェック(手順1)」まで読みました。本日もTIL形式です。

TIL

  • Bindingは、スコープをオブジェクトにまとめたものです。
  • evalを使用すると、文字列を直に実行するためコードインジェクションの脅威に晒される。自身が管理している文字列に対してのみevalを実行し、外部からの文字列に対しては実行をしない方が良い。
  • 6.3章ではクイズとして、アトリビュートをチェックするadd_checked_attributeを実装するという課題がありました。なかなか手が動かなく苦戦しています。

メタプログラミングRubyを読んでいます(7)

読んだ範囲

メタプログラミングRuby」の「5.3 特異メソッド」から「5.8 まとめ」まで読みました。本日は、TIL形式です。

TIL

  • クラスメソッドは、クラスの特異メソッドです。def obj.my_method; enddef A.my_method; end を比較するとクラスメソッドの定義形式は、特異メソッドと同一であることが分かります。
  • 特異クラスは、インスタンスを一つしか持てない制限があります。そのため、シングルトンクラスと呼ばれることがあります。
  • prependラッパーを使うと既存処理を上書くことが出来ます。参考としてサンプルコードを示します。

prependラッパーのサンプルコード

prependラッパーのサンプルコードを示します。C#method1の処理を上書こうと思います。

module M
  def method1
    p 'M'
    super
  end
end

class C
  prepend M

  def method1
    p 'C'
  end
end

C.new.method1

実行結果

"M"
"C"

メタプログラミングRubyを読んでいます(6)

読んだ範囲

メタプログラミングRuby」の「4.6 ドメイン特化言語を書く」から「5.2.1 クイズの答え」まで読みました。

知ったこと

共有スコープ

共有スコープという概念を知りました。複数のメソッドが同一の変数を共有する技法です。

:arrow_down: 文章だけでは、分かりにくいのでサンプルコードを示して終わりにします。

def share_scope
  n = 1

  Kernel.send :define_method, :counter do
    n
  end

  Kernel.send :define_method, :double  do
    n *= 2
  end
end

share_scope

p counter # => 1
double
p counter # => 2

以上です。リーフマンスを飲んで寝ます :zzz:

メタプログラミングRubyを読んでいます(5)

読んだ範囲

メタプログラミングRuby」の「4.4.1 カプセル化の破壊」から「4.5.4 呼び出し可能オブジェクトのまとめ」まで読みました。

知ったこと

コンテキスト探査機

コンテキスト探査機という用語を始めて知りました。instance_evalメソッドに渡したブロックのことを指します。 また、instance_evalメソッドは、オブジェクトのコンテキストで、ブロックを評価します。

使い慣れていないので、instance_evalメソッドを使ってみようと思います。

:arrow_down: Quarterオブジェクトのnum変数に0を代入する例です。

class Quarter
  attr_reader :num

  def initialize
    @num = 4
  end
end

quarter = Quarter.new

quarter.instance_eval do
  @num = 0
end

puts quarter.num # => 0

メタプログラミングRubyを読んでいます(4)

読んだ範囲

メタプログラミングRuby」の「3.3.3 動的プロキシ」から「4.3.4 クロージャのまとめ」まで読みました。

知ったこと

ブロックを定義した時の束縛について(4.3 ブロックはクロージャー)

ブロックを定義した時の束縛は、その時点での束縛を取得することを知りました。 小さなコードを実装して確かめてみます。

def greet
  name = '巻 真紀'
  yield
end

name = '世吹 すずめ'
puts greet { "こんにちは、 #{name}" } # => こんにちは、 世吹 すずめ

ブロックが定義されている時のselfmainなので、「巻 真紀」ではなく、「世吹 すずめ」に挨拶しています。

以上です :end:

メタプログラミングRubyを読んでいます(3)

読んだ範囲

メタプログラミングRuby」の「2.4.3 Refinements」から「3.3.3 動的プロキシ」まで読みました。 主な内容は、メソッドを動的に定義する方法についてでした。

TIL

Object#send を使用すると、メソッド名が引数となるので動的にメソッドを呼び出すことが出来ます。これを、動的ディスパッチと呼びます。 また、Module#define_methodを使用すると、動的にメソッドを定義することが出来ます。動的メソッドと呼びます。 動的ディスパッチと動的メソッドの違いは、動的にメソッドを 呼び出す定義するか です。

以上です :end:

メタプログラミングRubyを読んでいます(2)

読んだ範囲

メタプログラミングRuby」の「2.2.1 オブジェクトの中身」~「2.4.2 メソッドの実行」まで読みました。

TIL

  • Classクラスのスーパクラスは、Moduleクラスです。また、Moduleクラスのスーパークラスは、Objectクラスです。
  • モジュールのインクルードは、初回のみ有効です。逆に言うと2回目のインクルードは、無視されます。
  • クラスとモジュールの使い分けについて知りました。クラスは、インスタンスの生成や継承をしたい場合に使用します。一方、モジュールは他のクラスにインクルードしたい場合に使用します。