Interesting problem. There is undoubtedly much to
will learn from suggested solutions. Here it is:
I’m working with xhtml data, and want to extend
the REXML Element type with an inline? method that
returns true when
%w(a b code em emphasis i strong tt).member?(name)
That would be a simple addition to the Element class,
except that the program already contains an @inline
variable, and I don’t want to repeat myself. (Important,
because
is not considered an inline tag at the
moment. If at some point it turns out to be a good idea,
I want one list to modify, rather than two.)
The question is: How do I make the contents of the
variable known to the Element class?
Possibilities:
a) Use a global variable. This should work:
class REXML::Element
def inline?
return $inline.member?(name)
end
end
Of course, we don't much like global variables.
But that's one way to single-source the data and
make it available in two different classes.
b) Use a class variable:
class REXML::Element
@@inline = %w(a b code em emphasis i strong tt)
def inline?
return @@inline.member?(name)
end
end
Note: For a long time it wasn't clear to me that
it is impossible to initialize an instance variable
outside of a method. Coming from the Java world, I
just assumed that this would be legal:
class Foo
@bar = 2
end
But it isn't. (A fact that needs to be spelled out
somewhere, for Java types.) Class variables can be
initialized outside of a method, though, so this
solution works--but it violates the DRY principle.
Is there a way to use the data stored in the @inline
variable? Perhaps by using eval or instance_eval?
c) Add an an additional initialize call? Does this
work?
class REXML::Element
def initialize
@inline = %w(a b code em emphasis i strong tt)
end
def inline?
return @inline.member?(name)
end
end
This also leaves the DRY problem untouched, but
I find myself wondering whether initialize()
invocations are additive, as well. (I thought I
saw that once, but have been unable to find any
reference to the concept.)
d) Do some other clever thing with closures or eval,
so the Element object can reference data defined
in my class? Is there a way to do that?
Looking forward to responses. Much learning awaits.
:_)