user2490003
user2490003

Reputation: 11890

Accessing a child's constant from the parent's class

If a child inherits from the parent, it inherits the parents methods as well.

So how come an inherited method can't access the child's constants?

Example -

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

Doesn't the inherited method run "inside" the child class?

How can I get around this?

Upvotes: 3

Views: 1854

Answers (1)

kaikuchn
kaikuchn

Reputation: 795

No it doesn't. When you call Child.new.my_method it looks for the FOO constant in Parent and upwards.

I'm not going to question your approach and just provide you with a way to do what you want:

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

Now whenever you inherit from Parent the inherited hook will define a method my_method on the subclass. Notice that the scope of the block in the inherited method is still the class level scope of Parent. That's why I'm directly referencing the subclass (other) to get the constant. A way around this would be to use other.instance_exec { ... }.

Update

@maxpleaner pointed out (with the explanation provided by @CarySwoveland) that you could also retrieve the class via self and then retrieve the constant from it.

I.e., just do

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

That works because when calling child = Child.new; child.my_method the value of self within my_method will be child. And the class of child is obviously Child which knows the constant FOO.

Upvotes: 4

Related Questions