我写了以下代码:
class Actions
def initialize
@people = []
@commands = {
"ADD" => ->(name){@people << name },
"REMOVE" => ->(n=0){ puts "Goodbye" },
"OTHER" => ->(n=0){puts "Do Nothing" }
}
end
def run_command(cmd,*param)
@commands[cmd].call param if @commands.key?(cmd)
end
def people
@people
end
end
act = Actions.new
act.run_command('ADD','joe')
act.run_command('ADD','jack')
puts act.people
然而,当@commands
散列是类变量时,散列中的代码不知道@people
数组,这是可行的。
如何使@commands
散列成为类变量,并且仍然能够访问特定的对象实例变量?
当您调用Lambda时,可以使用instance_exec
为它们提供适当的上下文,查找注释以查看更改:
class Actions
# Move the lambdas to a class variable, a COMMANDS constant
# would work just as well and might be more appropriate.
@@commands = {
"ADD" => ->(name) { @people << name },
"REMOVE" => ->(n = 0) { puts "Goodbye" },
"OTHER" => ->(n = 0) { puts "Do Nothing" }
}
def initialize
@people = [ ]
end
def run_command(cmd, *param)
# Use instance_exec and blockify the lambdas with '&'
# to call them in the context of 'self'. Change the
# @@commands to COMMANDS if you prefer to use a constant
# for this stuff.
instance_exec(param, &@@commands[cmd]) if @@commands.key?(cmd)
end
def people
@people
end
end
编辑遵循@VictorMoroz和@mu的建议:
class Actions
def initialize
@people = []
end
def cmd_add(name)
@people << name
end
def cmd_remove
puts "Goodbye"
end
def cmd_other
puts "Do Nothing"
end
def people
p @people
end
def run_command(cmd, *param)
cmd = 'cmd_' + cmd.to_s.downcase
send(cmd, *param) if respond_to?(cmd)
end
end
act = Actions.new
act.run_command('add', 'joe')
act.run_command(:ADD, 'jill')
act.run_command('ADD', 'jack')
act.run_command('people') # does nothing
act.people
或
class Actions
ALLOWED_METHODS = %w( add remove other )
def initialize
@people = []
end
def add(name)
@people << name
end
def remove
puts "Goodbye"
end
def other
puts "Do Nothing"
end
def people
p @people
end
def run_command(cmd, *param)
cmd = cmd.to_s.downcase
send(cmd, *param) if ALLOWED_METHODS.include?(cmd)
end
end
act = Actions.new
act.run_command('add', 'joe')
act.run_command(:add, 'jill')
act.run_command('add', 'jack')
act.run_command('people') # does nothing
act.people