2013-01-20 84 views
3

我想編寫一個方法,該方法接受一個參數並創建另一個方法,該方法使用此參數命名。這裏是我的代碼使用class_eval創建方法

class Class 
    def createMethod(attr_name) 
    attr_name = attr_name.to_s 
    class_eval %Q{ 
     def #{attr_name} 
      puts "bar" 
     end 
    } 
    end 
end 

p Class.new.createMethod("foo").respond_to?(:foo) 

不幸的是,respond_to?(:foo)評估爲false。怎麼了?

回答

3

這是因爲class_eval是一個類方法,您可以在實例的上下文中調用它。執行此操作時

class Class 
    def createMethod(attr_name) 
    attr_name = attr_name.to_s 
    self.class.class_eval %Q{ 
     def #{attr_name} 
      puts "bar" 
     end 
    } 
    self # Return yourself if you want to allow chaining methods 
    end 
end 

這裏的輸出irb:你可以這樣做,而不是

irb(main):001:0> class Class 
irb(main):002:1> def createMethod(attr_name) 
irb(main):003:2>  attr_name = attr_name.to_s 
irb(main):004:2>  self.class.class_eval %Q{ 
irb(main):005:2"   def #{attr_name} 
irb(main):006:2"    puts "bar" 
irb(main):007:2"   end 
irb(main):008:2"  } 
irb(main):009:2> end 
irb(main):010:1> end 
=> nil 
irb(main):011:0> clazz = Class.new 
=> #<Class:0x007fd86495cd58> 
irb(main):012:0> clazz.respond_to?(:foo) 
=> false 
irb(main):013:0> clazz.createMethod("foo") 
=> nil 
irb(main):014:0> clazz.respond_to?(:foo) 
=> true 
+0

它仍然是錯誤的。 – ciembor

+2

它仍然是錯誤的原因是你的'createMethod'調用返回'nil',而不是實例,所以你不能鏈接'respond_to?'調用。你可以在'createMethod'的'end'之前加上'self',這就行了。 –

+1

不要發佈文字圖像,而是直接將實際文字複製並粘貼到您的文章中。文字圖像不容易解析,搜索或訪問。 –