使用派生类在Ruby中进行元编程

时间:2015-02-26 02:51:35

标签: ruby metaprogramming

我正在尝试编写一个打印类变量名及其值的方法。举个例子:

class A
    def printvars
        ???
    end
end

class <<A
    def varlist(*args)
        ???
    end
end

class B < A
    varlist :c
    def initialize(c)
        @c = c
    end
b = B.new(10)
b.printvars()

我希望输出为c => 10。但我不知道???中发生了什么。我尝试在varlist的主体中使用self.class_eval,但这不允许我存储args。我也尝试在类A中保留一个哈希值,然后在printvars中打印出来,但是单例类是A的超类,因此无法访问此哈希值。到目前为止,我所尝试的一切都无效。

我认为类似的东西必须是可能的,因为Rails做了与validates_ *方法相关的事情。理想情况下,我可以完全按预期工作,但即使是指向如何打印只是变量名称的指针(因此只是c作为输出)将是最受欢迎的。

2 个答案:

答案 0 :(得分:1)

您可能会喜欢这样的答案:What is attr_accessor in Ruby?

基本上,正如您所推测的那样,varlist需要是一个类方法,它采用变量参数列表(*args)。获得这些参数后,您可以使用sendrespond_to?或甚至instance_variable_get尝试任意数量的内容。注意,这些都不是真正推荐的,但我想回答一下你的问题。

另一半是你应该调查method_missing以了解validates_*之类的工作方式。 *部分需要你执行method_missing之类的操作,因为在你知道要查找的内容之前,你实际上无法执行module_eval。在魔术轨道方法的情况下,您不一定知道您在寻找什么!所以我们依靠内置的method_missing让我们知道所谓的内容。

对于funzies,请在IRB中尝试:

class A
  def method_missing(method, *args, &block)
    puts method, args.inspect
  end
end
A.new.banana(13, 'snakes')
A.new.validates_serenity_of('Scooters', :within => [:calm, :uncalm])

这有帮助吗?

答案 1 :(得分:1)

只需使用Module#class_variables

据我所知,你非常过于复杂。您所需要的只是预定义的Module#class_variables方法。您可以直接在类上调用它,或者如果要将其绑定到类的实例,则可以通过 self 调用它。例如:

class Foo
  @@bar = "baz"

  def show_class_variables
    self.class.class_variables
  end
end

Foo.class_variables
#=> [:@@bar]

foo = Foo.new
foo.show_class_variables
#=> [:@@bar]