From: Eric Armstrong Date: 2006-07-14T08:54:44+09:00 Subject: Initialize a variable in an extended class 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. :_)