From: "David A. Black" Date: 2007-10-20T10:27:00+09:00 Subject: Re: Class instance variable idiom Hi -- On Sat, 20 Oct 2007, ara.t.howard wrote: > > On Oct 19, 2007, at 5:09 AM, David A. Black wrote: > >>> in an instance context, require a 'self.class' prefix to invoke while >>> constants do not but this is not encapsulation - it's the breaking of it - >>> instances *should* be allowed to access the unfettered methods of their >>> class because requiring the 'self.class' prefix also makes them *public* >>> which, of course, seriously breaks encapsulation. >> >> I'm not following this, I'm afraid. If an object has a public method >> defined on it, and you call obj.meth, how does that break >> encapsulation? I guess it's the "*should*" I'm not understanding. > > in some languages instances of a class may call private/protected methods of > that class which, if you think about it, makes sense. in ruby, a method must > (ignoring xxx_eval and send) be exposed to the world if instances also need > to call it. so when using class instance vars you give instances one simple > option for accessing them: expose them through attr_accessor thereby also > exposing them to the world. for example I consider a class's instances to be part of the world outside the class, in particular the class as a first-class object with all the rights and privileges appertaining thereunto (or whatever they say when they give you a diploma :-) I don't think the decision on a class's part to expose state via (its own) attr_* methods is different whether it bears on objects that happen to be its own instances, or objects that don't. >> I'm not sure what the advantage is of generalizing the technical term >> "instance" that way. You can say that global variables are associated >> with an "instance" of a computer program, so they must be OK :-) >> > > heh. i actually meant it quite specifically with regard to classes - each > iteration of oo laguanges is breaking down the barrier between classes, > objects, and other constructs like modules. i think we all can see that the > distinction in ruby is largely artificial: layers put on top to make us see > them as distinct. i probably program a lot more class factories than your > average ruby programmer and, when you are working with classes at that level > you, correctly, are thinking of them as instances. but you also start > wondering why things like this don't work: > > class C > @var = 42 > class << self > p @var > end > end > > and this too > > class B < C > p @var > end But if objects started seeing each other's instance variables, then we'd have to come up with a replacement for the thing that today we call "instance variables". At least, I definitely think that there should be a way to maintain state strictly per-object; and if @vars didn't do it, something else would. So I prefer to think of @vars as already being the "something else" :-) > if you've programmed using prototypes this shouldn't really come as a > surprise: it's normal to expect classes that *are* objects to have some > mechanism for sharing or copying that object's state. in ruby you have to > resort to @@vars and other weirdness like klass.clone or klass.dup to get the > affect. It depends what you mean by "normal" :-) Since Ruby isn't a prototyped language, I wouldn't apply those design norms to it. Actually, #clone and #dup sound much better, as a way of generating new objects that essentially copy existing class objects, than instantiating classes. I don't expect C.new to be like C, whereas I do expect C.clone to be. > in summary it's correct, i think, in a language where classes are > first class objects to consider attributes of that class, like it's singleton > class and it's child classes, as *instance* data. I'm not sure I consider a singleton class or a child class exactly an "attribute" of a class (though that's another one of those terms that can slip around a lot). I'm also not convinced of the special bond between a class and its instances, especially any kind of bond of identity. > the lack of class setup with class instance variables isn't really a special > case though - any newbie would expect to be able to write this > > class C > @a, @b = 4, 2 > end > > class B < C > end > > and have @a and @b end up being initialized in B somehow. But then they learn about self and instance variables and they stop expecting it :-) But I'm not sure I'm following exactly what you mean here -- i.e., what your vision is of how it should behave as opposed (?) to how it does behave. David -- Upcoming training from Ruby Power and Light, LLC: * Intro to Ruby on Rails, Edison, NJ, October 23-26 * Advancing with Rails, Edison, NJ, November 6-9 Both taught by David A. Black. See http://www.rubypal.com for more info!