メタプログラミングRuby勉強
会#4
(Class Macro & Around Alias)
2013/07/20
@aegif
class_eval, instance_eval
• class_eval
 クラスのコンテキストに変更を加える
 フラットスコープを持つ為、class_eval()ブロック外の変
数にもアクセスできる
• instance_eval
 selfのみに変更を加える
2
クラスインスタンス変数
クラスに@var?
3
@@varじゃだめなの?
• @@varは・・・
 クラス変数だけど、クラスに属していない
 mainコンテキストに属している
 = Objectに属している
 ↓この実行結果は?
4
@@var = 1
class MyClass
@@var = 2
def self.var
@@var
end
end
puts "MyClass.var is #{MyClass.var}”
puts "Main context, @@var is #{@@var}"
実行結果
5
MyClass.var is 2
Main context, @@var is 2
6
対策
7
クラスインスタンス変数
を使う。なぜならクラス
はクラスのオブジェクト
だから。
特異メソッド
8
特定のオブジェクトに特
化したメソッド
特異メソッドのサンプル
• ↓この実行結果は?
9
class Book
def initialize(title, author)
@title = title
@author = author
end
attr_accessor :title, :author
end
a = Book.new('one world', 'jal')
b = Book.new('sky team', 'ana')
def a.mine
"#{title} is mine"
end
puts a.mine
puts b.mine
実行結果
10
one world is mine
eigen_method.rb:17:in `<main>': undefined method `mine' for #<Book:0x007fdeed04b158
@title="sky team", @author="ana"> (NoMethodError)
クラスマクロ
• クラス定義のなかで使える単なるクラスメソッド
• ↓例(obsoleteメソッド: クラスマクロ)
11
class Book
def self.obsolete(old_m, new_m)
define_method(old_m) do |*args, &block|
warn "WARNING: #{old_m}() is obsolete. Use #{new_m}()."
send(new_m, *args, &block)
end
end
obsolete :NOT_PROPER_METHOD, :proper_method
end
アラウンドエイリアス
• 旧メソッドにエイリアスを付ける
• 新しいメソッドを定義する
• 新しいメソッドから古いメソッドを呼び出す
• ↓例
12
class Fixnum
alias :old_plus :+
def +(num)
self.old_plus(num).old_plus(1)
end
end
おわり
13

メタプログラミングRuby勉強会#4