From: "trans. (T. Onoma)" Date: 2004-12-16T01:38:11+09:00 Subject: Re: initialize always On Wednesday 15 December 2004 09:47 am, Robert Klemme wrote: | "David A. Black" schrieb im Newsbeitrag | news:Pine.LNX.4.61.0412150450290.690@wobblini... | | > Hi -- | > | > On Wed, 15 Dec 2004, Robert Klemme wrote: | > > 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? | > | > My initial reaction is that it's too magic for my taste... too much | > written in "invisible ink". If I write: def meth; ...; end then I | > want it to fail if it's called with arguments. But I'm also not | > understanding the 'pro' point very thoroughly, or maybe I've just | > never had this problem. I think I'm just being thick, but can you | > explain a little more how/when/why this would be useful? | | Well, often you write a class and mixin a module that needs some state. | Currently the only safe way to initialize that is to write it like this: | | module Foo | def initialize(*a,&b) | super | @foo_state = "something" | end | end | | If you do not define initialize for a module you end up writing accessors | like this all the time: | | module Foo | def foo_state | @foo_state ||= "something" | end | end | | Which is less performant and has slightly different semantics (just think | of the case that nil or false is a legal value for @foo_state). | | So the idea was to safe some typing and change initialize methods without | arguments and without a super in them the way I described. | | Another option would be to disallow arguments and super for module | initialize and to do the change (implicit super etc.), which has some | reasons in favour of it but may break a lot of existing code. If I was | designing module initialization that's probably the way I'd do it. | Alternatively we could have a special method local_initialize that is | called automatically for each class in #ancestors. Yes, I think your idea is a good one for what it accomplishes but not for how it does so. It agree with David, it is too "magic". Nonetheless, your analysis is right on, and I think something really ought to be done about this. IMO, It happens far too often to continue to be overlooked. I also like the implicit super notion. But I think the best way to achieve it may be via an initialize callback. Barring that that your idea of an always called local_initialize is, AFAICT, the remaining alternative --and perhaps the better one anyways. T.