Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
class Dragon; end
# 使用 def 定義 class method
Dragon.instance_eval do
def foo
puts "bar"
end
end
Dragon.foo # bar
# 使用 def 定義 instance method
Dragon.class_eval do
def foo
puts "bar"
end
end
Dragon.new.foo # bar
# 使用 self.def 定義 class method
Dragon.class_eval do # 這裡改用 instance_eval 也可以耶(why?)
def self.foo
puts "bar"
end
end
Dragon.foo # bar
# ------------------------------------------------------------------------------------
# 使用 define_method 定義 instance method
class Dragon
define_method("foo") { puts "bar" }
end
Dragon.new.foo # bar
Dragon.class_eval do
define_method("foo") { puts "bar" }
end
Dragon.new.foo # bar
# 使用 define_method 定義 class method
class Dragon
class << self
define_method("foo") { puts "bar" }
end
end
Dragon.foo # bar
# 使用 define_method 嘗試定義 class method
Dragon.instance_eval do
define_method("foo2") { puts "bar" }
end
Dragon.foo2 rescue puts "fails" # 失敗找不到 method (why?)
# 使用 define_method 定義 class method
metaclass = (class << Dragon; self; end)
metaclass.instance_eval do # 這裡改用 class_eval 也可以耶(why?)
define_method("foo") { puts "bar" }
end
Dragon.foo # bar
# 使用 define_method 定義 class method (不用 metaclass 的話,只好定義在 Class 上)
Dragon.class.instance_eval do # 這裡用 class_eval 也可以
define_method("foo") { puts "bar" }
end
Dragon.foo # bar
String.foo # bar,所有類別都被污染啦!! bad idea!!
# ------------------------------------------------------------------------------------
# Recommended reading:
#
# http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/
# http://yugui.jp/articles/846
#
# My conclusion:
# mechanism self(current object) method definition(current class) new scope?
# class Dragon Dragon Dragon yes
# class << Dragon Dragon’s metaclass Dragon’s metaclass yes
# Dragon.class_eval Dragon Dragon no
# Dragon.instance_eval Dragon Dragon’s metaclass no
# "def method_name" define instance method for current class
# "define_method" defind instance method for self (must be class object)
# "def object.method_name" defines instance method for object's metaclass (a.k.a singleton method)
# New scope means that code inside the block does not have access to local variables outside of the block.
# class_eval, instance_eval 和 define_method 這幾個 method 不會有新的 scope 是 Ruby 跑 dynamic code 的利器,因為可以很方便讀取到 block 外的 local variable。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment