基本上界面設計師應該選擇這樣做,因爲有關範圍這個小動作,以及如何eval
和instance_eval
工作,檢查這個例子:
有2類Foo
和Boo
以下定義:
class Foo
def speak(phrase)
puts phrase
end
def self.generate(&block)
f = Foo.new
f.instance_eval(&block)
end
end
class Boo
attr_reader :name
def initialize(name) ; @name = name ; end
def express
Foo.generate { speak name}
end
end
一般來說,這應該能正常運行於大多數情況,但是像下面的語句某些情況下將發出一個錯誤:
Boo.new("someone").express #`express': undefined local variable or method `name' for #<Foo:0xb7f582fc> (NameError)
我們用不上這裏Boo
內Foo
情況下,這是因爲我們使用instance_eval
的實例方法,所以這是Boo
情況下定義的方法name
不在範圍爲Foo
實例。
爲了克服這些問題,最好重新定義產生如下:
class Foo
def speak(phrase)
puts phrase
end
def self.generate(&block)
f = Foo.new
block.arity < 1 ? f.instance_eval(&block) : block.call(f)
end
end
這是要評估取決於通過塊PARAMS代碼塊一個靈活的接口。現在,我們要通過當前Foo對象爲PARAM時,我們需要調用它實例的方法,讓我們重新定義Boo
,檢查express
和talk
:
class Boo
attr_reader :name
def initialize(name) ; @name = name ; end
def express
Foo.generate { |f| f.speak name}
end
def talk(anything)
Foo.generate { speak anything}
end
end
Boo.new("someone").express #=> someone
Boo.new("someone").talk("whatever") #=> whatever
我不知道怎麼回答這個問題。 – 2009-10-05 01:04:30
塊的存在定義了一個範圍...您可以在create_table中訪問它,併爲該表提供整數上下文。我不明白爲什麼不... – 2009-10-05 01:04:33
您可以將塊(或多或少)放入使用'instance_eval'調用的作用域中。 – Chuck 2009-10-05 01:15:36