From: Robert Klemme Date: 2004-12-15T21:47:15+09:00 Subject: Re: initialize always "Robert Klemme" schrieb im Newsbeitrag news:310832F34jr8cU1@uni-berlin.de... > > "trans. (T. Onoma)" 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