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.
Again, many apologies and thanks to those who replied attempting to understand my horrid writeup.
It is fixed now.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With