Get child constant in parent method - Ruby

10,091

Solution 1

EDIT: this answer is correct, although Wayne's is the more ruby-ish way to approach the problem.

Yes it is.

Your implementation will not work, because the parent tries to resolve EWOK locally. Parent doesn't have EWOK defined. However, you can tell Ruby to look specifically at the class of the actual instance the method was called on, to get EWOK.

this will work:

class Parent
  def go
    self.class::EWOK
  end
end

class Child < Parent
  EWOK = "Ewoks Rule"
end

class Child2 < Parent
  EWOK = "Ewoks are ok, I guess"
end

bob = Child.new
bob.go  # => "Ewoks Rule"

joe = Child2.new
joe.go  # => "Ewoks are ok, I guess"

what's going on here: in Parent's 'go', "self" will refer to the instance of the object that 'go' is actually being called on. i.e., bob (a Child), or joe (a Child2). self.class gets the actual class of that instance - Child in the case of bob, or Child2 in the case of joe. then, self.class::EWOK will retrieve EWOK from the correct class.

Solution 2

For a parent class to have access to a constant defined in a child class, wrap that constant in a method. Then the normal inheritance rules apply:

class Parent

  def ewok
    "Ewoks are lame"
  end

end

class Child < Parent

  def ewok
    "Ewoks rule"
  end

end

p Parent.new.ewok    # Ewoks are lame
p Child.new.ewok     # Ewoks rule

If the constant is expensive to initialize (a large hash, for example), the define it in a constant, but access it via a method:

class Parent

  EWOK = {
    # Enormous hash...
  }

  def ewok
    EWOK
  end

end
Share:
10,091
Justin
Author by

Justin

Updated on June 07, 2022

Comments

  • Justin
    Justin almost 2 years

    In Ruby, is it possible to go about getting a child's constant when I've called a parent's method through the child?

    Example:

    class Tester
      class Parent
    
        def go
          EWOCK
        end
      end
    
      class Child < Parent
        EWOCK = "EWOCKS rule"
    
      end
    end
    

    Then call Tester::Child.new.go and desire "EWOCKS rule" to come back?

    [Edit 3/31]

    Wow I'm REALLY sorry guys. I completely screwed up the explanation.

    • Parent should have been Child and Child should have inherited from base.
    • The call should have been to Child and not Parent

    Again, many apologies and thanks to those who replied attempting to understand my horrid writeup.

    It is fixed now.