2012-01-03 7 views
4

내가 다음 코드 작성 :이 @commands 해시 클래스 변수 인 경우, 그러나, 작동클래스 변수에 정의 된 λ/Proc 내에서 인스턴스 변수를 어떻게 사용합니까?

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 

을, 해시 내부의 코드는 @people 배열을 알 수 없습니다.

@commands 해시를 클래스 변수로 만들고 특정 개체 인스턴스 변수에 계속 액세스하려면 어떻게해야합니까? VictorMoroz의 @와 무의 권고 @ 다음

+1

'add','remove' 및'other' 메소드를 인스턴스 메소드로 정의하고'respond_to?'및'send' 메소드를 호출하여 호출하지 않는 이유는 무엇입니까? –

+0

'@ commands'를 왜 클래스 변수로 사용 하시겠습니까? –

+0

@Victor : 하나의 좋은 이유는 액세스 제어를 쉽게한다는 것입니다. 'send' 메소드와 메소드를 사용한다면'run_command' 메소드에서 사용할 수있는리스트가 필요합니다. 해시를 사용하면 사용 가능한 명령어와 그 구현을 하나의 멋진 패키지로 모을 수 있습니다. –

답변

6

당신은 찾아, 당신이 그들을 호출 람다에 대한 적절한 컨텍스트를 제공 할 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 
+0

아하! '인수는 블록 매개 변수로'instance_exec 전달됩니다. – maprihoda

1

편집 :

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