Robert Klemme
12/15/2004 12:45:00 PM
"Robert Klemme" <bob.news@gmx.net> schrieb im Newsbeitrag
news:310832F34jr8cU1@uni-berlin.de...
>
> "trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag
> news:200411271226.46187.transami@runbox.com...
> > It is rather a common occurrence that I find myself creating a mixin
> module
> > that has instance vars in it, for example:
> >
> > module Example
> > def add( ex )
> > @examples << ex
> > end
> > end
> >
> > class X
> > include Examples
> > end
> >
> > Now the class that includes this module requires @examples to be
> predefined.
> > But short of adding @examples = [] to the #initialize method of the
> class
> > (which would ruin the goal of using the module to begin with) one ends
> up
> > doing something like:
> >
> > module Example
> > def add( ex )
> > ( @examples || [] ) << ex
> > end
> > end
> >
> > But this seems quite computationally wasteful to me. Another
alternative
> is to
> > add an intialize to the module and a super call to the class:
> >
> > module Example
> > def initialize
> > @examples = []
> > end
> > def add( ex )
> > @examples << ex
> > end
> > end
> >
> > class X
> > include Examples
> > def initialize
> > super()
> > end
> > end
> >
> > But again, by having to modify the class we're defeating the one of
the
> basic
> > purposes of module "componentization": SOC.
> >
> > So I was thinking/wondering if it were possible to have an a variant
> > initializer that _always_ calls super? it would make sense to have one
> for
> > both begin and end positions. So the above example becomes:
> >
> > module Example
> > def initialize_pre
> > @examples = []
> > end
> > def add( ex )
> > @examples << ex
> > end
> > end
> >
> > class X
> > include Examples
> > end
> >
> > When X.new is called initialize_pre automatically proceeds the
> #initialize
> > method. #initialize_post would do the same for when the #initialize
> method
> > finishes. Of course these would automatically work their way up the
> entire
> > class/module chain.
> >
> > BTW this is not necessarily the same as method wraps (consider the
> subtle
> > differences) --rather these are strictly callbacks of initialization.
> >
> > Thoughts?
> > T.
>
> I think I did an RCR on this matter but I can't find it. Maybe I was
stuck
> or it got lost somewhere. I'll have to dig into this at home. If I find
> the info I'll get back. From what I remember basically the idea was to
> automatically invoke super under certain circumstances. The idea was to
> do that depending on the argument list and the presence of an explicite
> "super".
Finally today I found a sheet of paper while cleaning my desk. (It's good
to do that once in a while. :-))
It hadn't made it to an RCR though. The suggestion would have been this:
if a Module defines method initialize without an argument list then
implicitely change that to be initialise(*a,&b) and implicitely add super
as first line in the method: Thus
module Foo
def initialize
@bar = 0
end
end
becomes
module Foo
def initialize(*a,&b)
super
@bar = 0
end
end
Note: identifiers for arguments and block may have to be generated to be
unique.
All other cases (i.e. combinations of with / without argument list and
with / without occurrence of "super" in the body of this method) should
remain unchanged, because they would cause too much hassle.
Pro: this change allows for easy initialization of instance variables
needed by modules even if there are multiple modules included:
class Base
def initialize(x)
@x = x
end
end
class Test < Base
include Foo
include Bar
def initialize(a, b)
super(a)
@b = b
end
end
What do others think?
Kind regards
robert