class Warcraft
def initialize &block
instance_eval &block
end
def method_missing name, *args, &block
instance_variable_set("@#{name}".to_sym, args[0])
self.class.send(:define_method, name, proc { instance_variable_get("@#{name}")})
end
def game &block
@game = Game.new &block
end
class Game
def initialize &block
instance_eval &block
end
def method_missing name, *args, &block
instance_variable_set("@#{name}".to_sym, args[0])
self.class.send(:define_method, name, proc { instance_variable_get("@#{name}")})
end
end
end
warcraft = Warcraft.new do
name "Warcraft III"
battle_net :iccup
game do
side :sentinels
hero "Furion"
rune_appear_every 2
end
end
puts warcraft.inspect # => #<Warcraft:0x00000000be3e80 @name="Warcraft III", @battle_net=:iccup, @game=#<Warcraft::Game:0x000000009c6c38 @side=:sentinels, @hero="Furion", @rune_appear_every=2>>
如何访问嵌套方法?
puts warcraft.battle_net # => iccup
puts warcraft.side #=> #<Proc:0x000000010de6d8@dsl.rb:9 (lambda)>
puts warcraft.game #=> dsl.rb:18:in `instance_eval': block not supplied (ArgumentError)
puts warcraft.game.side #=> dsl.rb:18:in `instance_eval': block not supplied (ArgumentError)
答案 0 :(得分:1)
puts warcraft.game
会抛出错误,因为您的Warcraft#game
方法需要一个块,并且您将其称为属性访问器。
我不确定你在这里需要什么,但是如果你想使用Warcraft#game
方法获得当前游戏以及设置新游戏那么你可以返回当前游戏没有给出一个块,如下所示:
def game &block
if block_given?
@game = Game.new &block
else
@game
end
end