On Oct 18, 2007, at 11:22 AM, David A. Black wrote:

and ara responds to him but mostly to the general thread:

>
> I'm on record as saying that class variables are the thing I dislike
> most about Ruby, so I'll try to explain why.
>
> They break encapsulation.

i honestly don't think they do - inheritance breaks encapsulation.   
for example

  class A
    CONST = 42

    class << self
      def shared() 42.0 end
    end
  end

  class B < A
  end

  p B::CONST
  p B::shared

class vars are exactly like this - only with state that happens to be  
resettable.  i don't see anything particular about the way class vars  
behave that is different from constants or singleton (note the  
*single* in singleton methods that can be called on multiple  
objects!).  it's the concept of inheritance that breaks  
encapsulation, this is of course generally accepted by oop geeks, and  
ruby doesn't change this wart on oop's many graces.

> They are visible to a weird assortment of
> objects: class C, instances of C, class D < C, instances of D... all
> the same variable. This cross-section of objects doesn't have anything
> in common except that they can all see each other's class variables.
>

and constants and singleton methods....  of course class singleton  
methods, 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.

in point of fact inheritance is *designed* to break encapsulation so  
that we can reuse code and remain sane.  child classes, mixins,  
friend classes et al are all about tearing down the barriers between  
bits of code so we don't descend.into.dot.dot.dot.dot.hell and  
develop carpal tunnel from all that code pasting

> The prefix @@ makes it appear that they have some connection or
> kinship with instance variables. Actually, they're almost the
> opposite. Instance variables represent state on a strictly per-object
> basis. Class variables cut across many different objects and scopes.
> I would prefer them to look like $$this, since they're really a
> kind of restricted global variable rather than an extended instance
> variable.

i can see that.  still, they *are* associated with an instance - an  
instance of a class hierarchy.  i realize people don't generally seem  
to grasp this concept though.  the idea of switching syntax is a good  
one.  i hate $ because it looks like perl and perl is clearly evil.   
i'm not sure what would be better though.

>
> The worst thing about them, in my view, is the amount of confusion
> they have caused. The fact that there is something called a "class
> variable" -- and that it looks vaguely like an instance variable --
> has been a huge obstacle for people trying to get a grasp on the idea
> that classes are objects and can, via *instance* variable, have their
> own state. Class variables throw a big shadow over that otherwise very
> consistent and lucid state of things. I've seen this happen again and
> again for seven years.

absolutely correct.

>
> In Ruby > 1.8, class variables are going to be somewhat more strictly
> per-class. That's a mixed blessing. They're going to come closer to
> representing a class's state, but then the question will arise: why
> have both that *and* instance variables of classes? It's not
> impossible to answer that, but it's not a bad question.
>
> That sums up my views. Just so you know: I love Ruby madly :-) This is
> one of the very few areas where I dissent strongly from the way it's
> designed.
>

yeah i see all that.  still, i've deigned quite a few ruby classes  
and i can assure people that they will miss them when they are gone/ 
limited.  the reason, curiously, is that classes do not have an  
initialize method/hook.  let me explain: let's say you want to do  
something quite reasonable like so

   class Parser

     def self.bufsize(*value)
       value.size == 0 ? @@bufsize : self.bufsize=(value.first)
     end

     def self.bufsize=(value)
       @@bufsize = Integer value
     end

     bufsize 4242

     def initialize options = {}
       @bufsize = options[:bufsize] || @@bufsize
     end

   end

   Parser.new


that is to say you want to grab default initialization options from  
your class and you want users to be able to configure the class such  
that it stamps out instances with those defaults.  it's really nice  
if people can configure via the environment or like so

   Parser.bufsize 42

as i'm sure we can all agree.  obviously constants aren't really in  
order unless you want to use hackery like

   class Parser

     BUFSIZE = [ :value ]

     def self.bufsize=(value) BUFSIZE[0] = Integer value end

   ...

blechh!

i can hear people thinking "you need instance variables!"  sure, if  
you want to write totally non-reusable code.  why?  because if i do

   class Parser
     def self.bufsize(*value)
       value.size == 0 ? @bufsize : self.bufsize=(value.first)
     end

     def self.bufsize=(value)
       @bufsize = Integer value
     end

     bufsize 4242

     def initialize options = {}
       @bufsize = options[:bufsize] || self.class.bufsize
     end
   end

   Parser.new

then, seemingly, all is well.  but then

   class SubParser < Parser
     ...

now i have a problem: *only* the Parser class has an initialized of  
the class instance variable @bufsize - it's of course 'nil' in  
SubParser.  now, it's true that we can write something like

   class Parser

     def self.inherited other
       super if defined? super
     ensure
       other.init  ### note that this must be *public* less we result  
to class_eval...
     end

     def other.init
       bufsize 4242
     end

     init()

this all starts to get just as confusing as the current situation.  i  
can hear people now: "why is it so hard to inherit class variables in  
ruby?"

in short there are a million reasons to use class variables revolving  
around the glitch that class inheritance in ruby does not provide a  
straightforward way for child classes to have any sort of setup step  
performed and that class variables let you perform that setup once in  
a way that is inherited and yet settable by client code.

anyhow i really think it's the syntax, not the concept, that is cause  
for confusion.

my 2cts.

ps.  there are a lot of powerful concepts in ruby that are mostly mis- 
understood: closures, mixins, singleton classes, callcc, throw/catch,  
and lambda abstraction are part of what allows ruby to grow in  
usefulness beyond the realm of the 'mere scripting language' some  
people set out to learn. i would be loathe so any of them vanish.

pss.  encapsulation is vastly overrated.  when is that last time you  
used 'protected' in any ruby code?  ;-)

a @ http://codeforpeople.com/
--
it is not enough to be compassionate.  you must act.
h.h. the 14th dalai lama