instance_eval解决方案
这里有一种方法可以实现你想要的。
instance_eval
使用block通常比
eval
.
item
方法并不太复杂:
-
它首先创建一个具有
item_name
-
如果有一个块,它将在
项目
这意味着在该块中执行的代码将知道
@name
和
@children
.
-
如果
children
已定义,表示当前
项目
方法已在另一个的块内调用
项目
.电流
项目
应添加到
儿童
父母的
项目
.
class Item
attr_accessor :name, :children
def initialize(name)
@name = name
@children = []
end
def inspect
"#{name} #{children}"
end
end
def item(item_name, &block)
item = Item.new(item_name)
item.instance_eval(&block) if block
children << item if defined?(children)
item
end
foo_item = item('foo') do
item('bar') do
item('biz')
item('boz')
end
item('baz')
end
p foo_item
#=> foo [bar [biz [], boz []], baz []
调试模式
以下是带有调试信息的相同代码:
class Item
attr_accessor :name, :children
def initialize(name, indent = "")
@name = name
@children = []
@indent = indent
end
def inspect
"#{name} #{children}"
end
end
@indent = ""
def item(name, &block)
puts "#{@indent}Creating item #{name}"
item = Item.new(name, @indent + " ")
item.instance_eval do
puts "#{@indent}Inside item #{@name}"
end
if block
puts "#{@indent} Block is here. Executing it in item #{item.name}"
item.instance_eval(&block)
end
if defined?(children)
puts "#{@indent}Inside item #{@name}! Adding item #{item.name} to #{@children}"
children << item
end
item
end
它输出:
Creating item foo
Inside item foo
Block is here. Executing it in item foo
Creating item bar
Inside item bar
Block is here. Executing it in item bar
Creating item biz
Inside item biz
Inside item bar! Adding item biz to []
Creating item boz
Inside item boz
Inside item bar! Adding item boz to [biz []]
Inside item foo! Adding item bar to []
Creating item baz
Inside item baz
Inside item foo! Adding item baz to [bar [biz [], boz []]]