从父类访问子类的常量

3
如果一个子类继承了父类,它也会继承父类的方法。
那么为什么继承的方法无法访问子类的常量呢?
例如 -
class Parent
  def my_method
    puts "Value of FOO is #{FOO}"
  end
end

class Child < Parent
  FOO = "bar"
end

Child.new.my_method #=> NameError: uninitialized constant Parent::FOO

继承方法不是运行在子类“内部”吗?

我该如何解决这个问题?


5
你可以在 my_method 中使用 self.class::FOO 而不是 FOO 来解决这个问题。 - max pleaner
@maxpleaner,你能把那个作为答案发布一下吗?或者提到 self - Cary Swoveland
@CarySwoveland 我有点尴尬地说,我没有一个好的解释为什么它能够工作,我只知道它确实可以 :D - max pleaner
1
@max,如果执行c=Child.newc.my_method,那么在my_methodself就是c。我认为就是这么简单。 - Cary Swoveland
@CarySwoveland,但是为什么您可以在Child的实例方法中访问Child :: Foo? - max pleaner
1
@max,你建议在Parent#my_method中使用self.class :: FOO。如果执行c = Child.newc.my_method,则在my_method内部self等于c,因此self.class :: FOO => c.class :: FOO => Child :: FOO =>'bar',就像my_method的所有者是Child一样。对吗? - Cary Swoveland
1个回答

4
不,它并不会。当你调用Child.new.my_method时,它会在Parent及以上的范围内查找FOO常量。
我不会质疑你的方法,只是提供一种实现你想要的方式:
class Parent
  def self.inherited(other)
    other.define_singleton_method(:my_method) do
      puts "Value of FOO is #{other.const_get(:FOO)}"
    end
  end
end

现在,每当您从Parent继承时,继承的钩子将在子类上定义一个my_method方法。请注意,在inherited方法中块的范围仍然是Parent的类级别范围。这就是为什么我直接引用子类(other)来获取常量的原因。
解决这个问题的方法是使用other.instance_exec { ... }

更新

@maxpleaner指出(由@CarySwoveland提供的解释),您还可以通过self检索类,然后从中检索常量。

即,只需执行

class Parent
  def my_method
    puts "Values of FOO is #{self.class.const_get(:FOO)}"
  end
end

那是因为在调用child = Child.new; child.my_method时,my_method内部的self值将被设置为child。而child的类显然是Child,该类知道常量FOO

有没有一种方法可以使这个适用于静态方法? - developius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接