From: dblack@... Date: 2003-02-23T00:46:06+09:00 Subject: Re: Style question: using 'block_given?' Hi -- On Sat, 22 Feb 2003, Brian Candler wrote: > On Sat, Feb 22, 2003 at 04:05:59PM +0900, dblack@candle.superlink.net wrote: > > It's probably most useful in an accessor. For example, if you want to > > keep a running tally of how many instances of a class have been > > created: > > > > class C > > class << self; protected; attr_accessor :instances; end > > @instances = 0 > > > > def initialize > > self.class.instances += 1 > > end > > end > > I think we need a RubyBlackMagic page on the Wiki :-) Whoops -- delete the 'protected'. I was trying to see what that would do, and forgot to delete it before cutting and pasting. (It was two in the morning. I was also typing "fetchmail -a" on an irc channel....) > I am probably being obtuse, but in order to decipher this I had to go the > long way round, starting with an analogy with with the normal usage of the > 'class < So in the above, 'a' has been changed from an instance of 'Foo' to an > instance of an anonymous (singleton) class derived from 'Foo'. Yes, though it's a very particular kind of change. a.class will still report Foo. The singleton class is anonymous and sort of "transparent" -- meaning, whatever information it fails to supply (such as a name for itself) will come from the object's historical class. (That's one of the differences between the singleton class mechanism and subclassing.) > Now, taking what you wrote: [snip ... class << C ...] > Therefore, C.new generates an instance of an object whose class is this > 'enhanced' class. > > Consistent? Yes. Predictable? Perhaps, if you've seen it before :-) Ah, but you *have* seen it before -- class << a in your example :-) The consistency is what makes it predictable: what works for one object works for another, even if one is a Foo and one is a Class. (With the exception of Fixnums and Symbols, which you can't do this with.) > Anyway, taking the original example which was something like: > > class Tree > @data = nil > @kids = nil > def initialize(data) > @data = data > @kids = [] > end > end > > then I don't think it's immediately obvious at a glance that: > > 1. the first uses of '@data' and '@kids' are something completely different > to the second uses That's just practice -- you get a sense of what 'self' is, and any "@x = y" type of assignment pertains to self's instance variables. > 2. the things that you've created by the first assignments to '@data' and > '@kids' are actually fairly well hidden; the only way you can get at > them is via subclassing Class, or through class methods Except... C's instance variables are visible only when self is C, and subclassing Class results in a new instance of Class, which has its own instance variables: class C @x = 1 end class D puts @x # nil end (Same as for instance variables across the board: they are only visible when their owner is 'self'.) > 3. even if you realise that the first uses of '@data' and '@kids' belong > to the class and not to an instance of an object of that class, they > are still not the same thing as '@@data' and '@@kids', which belong to > the class but in a different way: > > If you saw those things at a first glance, then I'd say you are a RubyWizard > :-) I did see them at a glance, but I must respectfully decline the title, since if we call me that, we'll start running out of words to describe the people higher up in the inheritance chain :-) I'm just a veteran of some long sessions of communing with the "classes are instances too" concept. See also if that's helpful. David -- David Alan Black home: dblack@candle.superlink.net work: blackdav@shu.edu Web: http://pirate.shu.edu/~blackdav