2012-04-19 2 views
0

좋아, 이것이 나를 미치게합니다. 이 코드의 요점은 object.plusnum 형식 인 경우 동적으로 메서드를 추가 할 수 있어야한다는 것입니다. num은 임의의 숫자입니다. 나는 이것을 어떻게 작동시키는 지 잘 모릅니다. 이것은 지금까지 나의 최선의 시도이지만, 현재 몇 가지 오류가 발생하고 있습니다.Ruby에서 메타 프로그래밍 오류가 발생했습니다.

코드 :

class Adder 
def initialize(_val) 
    @start_value = _val 
end 

def method_missing(method_name, *args) 
    method = method_name.to_s 
    if method.start_with?("plus") then 
     num = method[4 .. method.length] 
     if (/^[\d]+(\.[\d]+){0,1}$/ === num) then 
      number = Integer(num) 
      self.class_eval("def #{method} return @start_value + #{number} end") 
     else 
      super 
     end 
    else 
     super 
    end 
end 

end 

나는 현재지고있어 오류가 "class_eval"입니다 정의되지 않습니다. 나는 metaprogramming과 루비에 꽤 새로운데, 이것은 나를 미치게 만든다.

답변

2

간단한 반환 나는 당신이 그것을 가지고 생각할 수있는 모든 잘못된 :

그래서 아마 당신은 그것을 두 번 호출하는 대신, 처음으로 수확량 다른 결과에 대한 메소드를 호출 이 메서드는 정의 후 즉시 호출됩니다. 또한 - 꽤 복잡한 정규식을 사용하고 값을 Integer으로 변환하고 점 뒤에 모든 숫자를 놓습니다.

class_eval을 사용하고 있습니다. 보통 보안 상 및 성능상의 이유로 블록을 사용해야합니다. 나는 그것을 볼 수있는 방법은 방법

:

class Adder 
    def initialize(val) 
    @start_value = val 
    end 

    def method_missing(method_name, *args) 
    if method_name.to_s =~ /^plus(\d+)$/ 
     self.class.class_eval do 
     define_method(method_name) { @start_value + $1.to_i } 
     end 
     self.send(method_name) 
    else 
     super 
    end 
    end 
end 
0
  1. 당신은하지 가산기의 인스턴스에서 Adder 클래스에 class_eval를 호출해야합니다.
  2. 문자열이 유효한 Ruby가 아닙니다. #{method} 뒤에 괄호를 넣으십시오.

코드의 새로운 버전 :

class Adder 
def initialize(_val) 
    @start_value = _val 
end 

def method_missing(method_name, *args) 
    method = method_name.to_s 
    if method.start_with?("plus") then 
     num = method[4 .. method.length] 
     if (/^[\d]+(\.[\d]+){0,1}$/ === num) then 
      number = Integer(num) 
      self.class.class_eval("def #{method}() return @start_value + #{number} end") 
     else 
      super 
     end 
    else 
     super 
    end 
end 

end 

a = Adder.new(0) 
a.plus1 

자신을 위해 말하기, 나는이 방법을 위로 구축하는 방법과 단지 점차적으로 교체 한 후

class Adder 
end 

Adder.class_eval("def plus1() return 0 + 1 end") 
a = Adder.new 
a.plus1 

와 함께 시작하는 것입니다 한 번에 모든 것을 쓰는 것이 아니라 구성 가능한 값을 가진 유선 값.

1
class Adder 
def initialize(_val) 
    @start_value = _val 
end 

def method_missing(method_name, *args) 
    method = method_name.to_s 
    if method.start_with?("plus") then 
     num = method[4 .. method.length] 
     if (/^[\d]+(\.[\d]+){0,1}$/ === num) then 
      number = Integer(num) 
      self.class.class_eval("def #{method}() return @start_value + #{number} end") 
      eval(method) 
     else 
      super 
     end 
    else 
     super 
    end 
end 

end 

a = Adder.new(0) 
a.plus1 

메소드를 호출하기 위해 마지막에 eval (메소드)을 추가해야합니다. 그렇지 않으면 메소드를 작성하기 위해 nil이 리턴됩니다. 또는 당신은 반환 @start_value + # {수}

관련 문제