Ruby:为什么实例eval在类上创建实例方法而不是类方法

时间:2016-08-28 12:55:13

标签: ruby-on-rails ruby metaprogramming

我想动态创建类方法test,为此我在define_method内使用instance_eval方法。我期望下面的代码创建类方法test,但代码是创建实例方法test。这可能是什么原因?下面是我的代码。

module Accessor
  def define_accessor_for_class(method)
    self.instance_eval do
      define_method :test do
      end
    end
  end
end




class Employee
  extend Accessor
  define_accessor_for_class :name
end


Employee.name = "sanjay"
Employee.name

Employee.instance_methods(false) ==> [:test]
Employee.methods(false) => []

2 个答案:

答案 0 :(得分:2)

instance_eval更改self,即实例变量和无接收器消息发送的动态上下文。它不会更改default definee,即非限定方法定义的动态上下文。

在您的情况下,由于您的方法定义没有任何动态,因此根本没有理由使用动态元编程,您只需使用合格的方法定义:

module Accessor
  def define_accessor_for_class(method)
    def self.test; end
  end
end

class Employee
  extend Accessor
  define_accessor_for_class :name
end

Employee.instance_methods(false) #=> []
Employee.methods(false)          #=> [:test]

如果出于某种原因,您需要动态,则可以使用Object#define_singleton_method代替:

module Accessor
  def define_accessor_for_class(method)
    define_singleton_method(:test) do end
  end
end

class Employee
  extend Accessor
  define_accessor_for_class :name
end

Employee.instance_methods(false) #=> []
Employee.methods(false)          #=> [:test]

答案 1 :(得分:1)

您需要使用define_singleton_method代替define_method

module Accessor
  def define_accessor_for_class(method)
    self.instance_eval do
      define_singleton_method :test do
      end
    end
  end
end

Singleton方法是生活在单例类中的方法,仅适用于单个对象(与该类的所有实例可用的常规实例方法不同)。在你的课堂上,它会像一个班级方法。

结果如下

Employee.instance_methods(false) #=> []
Employee.methods(false)          #=> [:test]