Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get child constant in parent method - Ruby

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.

like image 324
Justin Avatar asked Mar 30 '12 19:03

Justin


2 Answers

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.

like image 143
YenTheFirst Avatar answered Sep 16 '22 15:09

YenTheFirst


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 
like image 25
Wayne Conrad Avatar answered Sep 18 '22 15:09

Wayne Conrad