在父级中使用派生类的属性

时间:2014-04-30 07:41:19

标签: ruby-on-rails ruby-on-rails-4

我尝试使用define_method为从超类继承的类创建其他方法:

class Child < Parent
  ADDITIONAL_METHODS += ['xyz', 'qwe']
end

class Parent
  ADDITIONAL_METHODS = ['common']
  ADDITIONAL_METHODS.each do |key|
    define_method key do
      ...
    end
  end
end

这不起作用,因为ADDITIONAL_METHODS始终取自Parent类,并且唯一创建的方法是common。有没有办法从派生类访问该属性?

1 个答案:

答案 0 :(得分:3)

示例代码不起作用,因为在声明Parent之前,您使用Child作为Parent的祖先。

这会产生此错误:

uninitialized constant Parent (NameError)

如果它实际上适合您,则意味着Parent确实在Child之前声明。在这种情况下,#each上的ADDITIONAL_METHODS循环在Child甚至存在之前执行,因为您在方法定义之外的类中给出的指令会立即执行:

class Foo
  def initialize
    puts "second"
  end

  puts "first"
end

Foo.new
puts "third"

输出:

first
second
third

解决方案

您可能希望实现一个类方法并立即调用它来执行该操作。

class Parent
  private

  def self.add_my_methods( *methods )
    ( methods.empty? ? [ 'common' ] : methods ).each do |key|
      define_method key do
        p key
      end
    end
  end

  add_my_methods # will implement "common"
end

class Child < Parent
  add_my_methods 'xyz', 'qwe'
end


c = Child.new
c.common # outputs "common"
c.xyz    # outputs "xyz"
c.qwe    # outputs #qwe"

这是后代元编程的常用模式,就像您可能已经使用#has_many#before_filter等方法遇到过它。