【问题标题】:How do I dynamically create class method by using a variable from outside a singleton class?如何使用单例类外部的变量动态创建类方法?
【发布时间】:2016-09-19 15:38:51
【问题描述】:

在 MyClass 中,我有一个类方法可以动态创建某些实例方法(使用 define_method)。但是,我也想动态创建类方法。

如下所示,我在这个范围内使用class << self 并调用define_method(实际上我不确定范围是否是正确的词,尽管块似乎也不正确。什么是引用 class << self?) 内执行的所有内容的正确术语来定义类方法。

但是,我想使用来自class << self 之外的变量来命名类方法,即column_name

因此,我想在class << self 中使用变量column_name 来命名define_method 中的类方法。 当我尝试运行 create_methods 时出现错误:

NameError: 未定义的局部变量或方法 'column_name' for # from (pry):7:in 'singleton class'

class MyClass
  @columns = ['col1', 'col2']  
  def self.create_methods  
    @columns.each do |column_name|
      define_method(column_name) { |column_name| puts column_name }    
      class << self    
        define_method(column_name) { |column_name| puts "class_method defined" }      
      end  
    end  
  end
end

如何从单例类中访问变量?在这里完成我想要完成的事情(创建类方法)的最佳方式是什么?

注意:我已经尝试过define_singleton_method 方法,它似乎对我想做的事情有效。它是否完全完成了我想要做的事情?即使是这样,我关于使用class &lt;&lt; self 的问题仍然存在。

【问题讨论】:

  • 在我看来,您正在动态尝试在另一个类方法中创建一个类方法。我不太清楚为什么。
  • 我正在实现 Active Record 的一些基本功能。特别是我有一个 SQLObject 类,它对 SQLite 数据库进行查询。我的模型继承自 SQLObject。后者有一个类方法,它根据模型类的名称生成一些方法。其中一种方法是类方法“find”,它通过 id 查找记录。但我还想生成“find_by_column_name”方法,该方法在数据库中查询具有特定列的给定值的条目。这一切都应该自动完成,只需要继承类的名称。

标签: ruby


【解决方案1】:

要完成你想要的,你可以这样做:

class MyClass
    @@columns = ['col1', 'col2']  

    def self.create_methods  
        @@columns.each do |column_name|
            define_method(column_name) { |column_name| puts column_name }    
        end

        class << self
            @@columns.each do |column_name|
                define_method(column_name) { |col_name| puts "class_method defined" }      
            end
        end
    end
end

注意:使用def self."method_name" 定义类方法可以让您使用实例变量(即@columns),这就是我重新定义为类变量的原因。

当你打开单例类(class &lt;&lt; self)时,你失去了之前的作用域,所以你不能得到column_name(名称错误)。但可以访问类变量。

在您的情况下,请使用define_singleton_method。如下:

class MyClass
    @columns = ['col1', 'col2']  

    def self.create_methods  
        @columns.each do |column_name|
            define_method(column_name) { |column_name| puts column_name }    
            define_singleton_method(column_name) { |col_name| puts "class_method defined" }
        end
    end
end

【讨论】:

  • 如果我使用类实例变量@columns 而不是类变量@@columns,为什么第一个选项不起作用?
  • 从这个链接stackoverflow.com/questions/15773552/…看来,类实例变量只对类方法可用,对实例方法不可用,而类变量对实例方法和类方法都可用。
  • @evianpring 是的,@columns 是一个类实例变量(没有 getter 方法)。但变量column_name 是本地变量,不能从单例类class &lt;&lt; self 访问。
猜你喜欢
  • 2011-03-30
  • 2017-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多