I’m no doubt missing something obvious but I found this a little
confusing. I would have expected the constant lookup to start in Bar
and therefore succeed. Instead, it appears to start in Base where Foo
is not defined.
In message “Re: Constant lookup starting in superclass, not derived
class”
on Mon, 11 Sep 2006 21:59:21 +0900, “Chris R.” [email protected] writes:
|I’m no doubt missing something obvious but I found this a little
|confusing. I would have expected the constant lookup to start in Bar
|and therefore succeed. Instead, it appears to start in Base where Foo
|is not defined.
|
|class Base
| def foo
| p Foo
| end
|end
Can anyone explain what is happening please?
Constants, unlike methods and instance variables, are “quasi”-lexicaly
scoped. (I say “quasi” because a sub class can assign to a constant
without munging its parent class’s constant) One way of getting around
this particular situation is to use #const_get. e.g.:
class Base
def foo
p self.class.const_get(‘Foo’)
end
end
Foo is not in the scope of Base so it cannot be looked up the way you
did it. See Matz’s explanation how to access it nevertheless.
Generally this form of dependency is not desirable, because the base
class should be self contained and not depend on any sub classes. In
Java you could make Base abstract and add an abstract method that will
return a Class instance - but in Ruby there are no abstract classes.
Do you have any suggestions of alternative implementation?
I’d rather not use the self.class.const_get method as it clutters the
code somewhat.
I wonder if I’m trying to refactor two seemingly identical methods
that are in fact different.
class Main1
def Foo; end
def foo
Foo.new
end
end
class Main2
def Foo; end
def foo
Foo.new
end
end
At this point, I created a superclass to hold the common foo method
definition. However, if I had the fully qualified namespace for Foo
(Main1::Foo and Main2::Foo) in each method they would be different and
I wouldn’t have moved them. Maybe that is part of my problem.
I understand the point about the base class depending on child classes
not being desirable. What about a module relying on constants defined
elsewhere (does the same apply)?
PS: Please don’t top post and trim quotings - that way others can easier
follow threads here.
Or to put it more clearly, ‘please trim quotations and don’t top post.’
Drifting wildly away from the topic, the ambiguity in the original
request reminds me of the signs posted by Southwark Council on some of
their properties: ‘Do not exercise or allow your dog to foul the
estate.’ (People seem to follow the first half better than the
second.)
I was bumping against the same wall you are for a while. Later, i
learned how to use meta classes and then realized that they gave me
exactly what i was looking for.