【问题标题】:Passing values into a class created with Class.new将值传递给使用 Class.new 创建的类
【发布时间】:2012-11-23 13:03:33
【问题描述】:

我有一个名称和值列表,我正在尝试读取并转换为类,因此我使用的是Class.new

我想要的最终结果是许多类的工作方式就像定义如下:

module MyMod
  class AA < Base
    def self.value
      value1
    end
  end

  class AB < Base
    def self.value
      value2
    end
  end

  ...
end

我当前的代码如下:

name = 'AA'
value = 'test'
MyMod.const_set name, Class.new(Base) do
  ???
end

设置名称效果很好,但还没有弄清楚我需要在块中获取 value 的内容。调用 def 不起作用,因为 value 的闭包丢失了。

我已经设法让事情顺利进行:

temp = const_set name, Class.new(Base)
temp.define_singleton_method(:value) { value }

但是,似乎应该有一种方法可以使用 Class.new 块来实现。另外,我真的不确定define_singleton_method 是否将方法放在正确的位置。它在我的测试中有效,但我不确定该方法是否真的在我认为的位置或调用链上的其他位置。我尝试了class_variable_setattr_readerclass_evalinstance_eval 和其他的各种组合,但到了只能猜测和检查的地步。我想我还没有完全理解元编程:-/

【问题讨论】:

  • 你能提供一些你为什么要这样做的背景吗?也许还有另一种方式。我喜欢元编程(我正在使用 Smalltalk),但动态生成类(我尝试过)很少是最佳解决方案。
  • @ewernli 我有一个有效名称:值对的简短列表。我为它们创建了一个类,并保留了通过读取文件生成的所有有效实例的列表。我不希望创建任意实例,因此在该列表上有一个查找方法而不是初始化程序。我正要创建另一个类,它将封装第一个类的“实例”,存储对它的引用和一些额外的数据。基于这个命名,我意识到制作类并拥有它们的实际实例可能会更好。我认为它很好地模拟了领域,但没有考虑性能。

标签: ruby metaprogramming


【解决方案1】:

如果我正确理解了你的问题,这应该对你有用:

class Base
end

class AA < Base

  name = :Blah
  klass = self.const_set name, Class.new(Base)

  class << klass
    def value
      __method__
    end
  end

end

p AA::Blah.value
#=> :value

更新:似乎您希望在块中定义它:

class Base
end

class AA < Base

  name = :Blah
  klass = Class.new(Base) do

    class << self
      def value
        __method__
      end
    end

  end
  self.const_set name, klass

end

p AA::Blah.value

你试试这个:

const_set name, Class.new(Base) do
  ...
end

它不起作用,因为该块引用const_set 而不是Class.new

如果您更喜欢define_singleton_method 而不是class &lt;&lt; self

class Base
end

class AA < Base

  name = :Blah
  klass = Class.new(Base) do

    self.define_singleton_method :value do
      __method__
    end

  end
  self.const_set name, klass

end

最后,如果您真的想立即定义它们,请使用括号而不是 do...end

class Base
end

class AA < Base

  name = :Blah
  self.const_set name, Class.new(Base) {

    self.define_singleton_method :value do
      __method__
    end

  }

end

Here 是一个工作演示

【讨论】:

  • 解决方案的关键是“它不起作用,因为块引用const_set 而不是Class.new”。谢谢!重构使其余部分过时,但它们是有用的示例。
  • 进一步的重构使其余部分非常有用,再次感谢您!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-27
  • 2023-02-25
  • 2015-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多