Class instance variable idiom

I am using this technique for class instance variables:

class << self
  def set_foo(s)
    @foo = s
  end
  alias :foo= :set_foo

  def foo
    @foo
  end
end

Then to reference foo from an instance of the class (or subclass), I do:

  self.class.foo

Is there a cleaner way, in particular for the reference of the class
instance variable, to do this?

Thank you,
pedz

···

--
Posted via http://www.ruby-forum.com/.

Hi --

I am using this technique for class instance variables:

class << self
def set_foo(s)
   @foo = s
end
alias :foo= :set_foo

def foo
   @foo
end
end

Then to reference foo from an instance of the class (or subclass), I do:

self.class.foo

Is there a cleaner way, in particular for the reference of the class
instance variable, to do this?

Yes:

   class C
     class << self
       attr_accessor :foo
     end
   end

David

···

On Thu, 18 Oct 2007, Perry Smith wrote:

--
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!

class << self
   attr_accessor :foo
end

  robert

···

On 17.10.2007 22:10, Perry Smith wrote:

I am using this technique for class instance variables:

class << self
  def set_foo(s)
    @foo = s
  end
  alias :foo= :set_foo

  def foo
    @foo
  end
end

Then to reference foo from an instance of the class (or subclass), I do:

  self.class.foo

Is there a cleaner way, in particular for the reference of the class
instance variable, to do this?

Just out of curiosity, why do you want a "class instance variable"
instead of a class variable?

···

On Oct 17, 4:10 pm, Perry Smith <p...@easesoftware.com> wrote:

I am using this technique for class instance variables:

class << self
  def set_foo(s)
    @foo = s
  end
  alias :foo= :set_foo

  def foo
    @foo
  end
end

Then to reference foo from an instance of the class (or subclass), I do:

  self.class.foo

Is there a cleaner way, in particular for the reference of the class
instance variable, to do this?

Robert Klemme wrote:

···

On 17.10.2007 22:10, Perry Smith wrote:

  end
end

Then to reference foo from an instance of the class (or subclass), I do:

  self.class.foo

Is there a cleaner way, in particular for the reference of the class
instance variable, to do this?

class << self
   attr_accessor :foo
end

  robert

Thanks!

Do I still do the self.class.foo to access it?

--
Posted via http://www.ruby-forum.com/\.

Probably because class variables have @@various issues as has
discusses before. I would also recommend to not use them.

Kind regards

robert

···

2007/10/18, Brian Adkins <lojicdotcom@gmail.com>:

On Oct 17, 4:10 pm, Perry Smith <p...@easesoftware.com> wrote:
> I am using this technique for class instance variables:
>
> class << self
> def set_foo(s)
> @foo = s
> end
> alias :foo= :set_foo
>
> def foo
> @foo
> end
> end
>
> Then to reference foo from an instance of the class (or subclass), I do:
>
> self.class.foo
>
> Is there a cleaner way, in particular for the reference of the class
> instance variable, to do this?

Just out of curiosity, why do you want a "class instance variable"
instead of a class variable?

Hi --

···

On Thu, 18 Oct 2007, Perry Smith wrote:

Robert Klemme wrote:

On 17.10.2007 22:10, Perry Smith wrote:

  end
end

Then to reference foo from an instance of the class (or subclass), I do:

  self.class.foo

Is there a cleaner way, in particular for the reference of the class
instance variable, to do this?

class << self
   attr_accessor :foo
end

  robert

Thanks!

Do I still do the self.class.foo to access it?

Yes. The call to attr_accessor will create singleton methods for use
by the class object Foo.

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!

yes, and

   self.class.foo = obj

to invoke the writer/setter method.

Gary Wright

···

On Oct 17, 2007, at 4:22 PM, Perry Smith wrote:

Do I still do the self.class.foo to access it?

What issues have you experienced with them to cause you to not
recommend them? I rarely have a need for either class variables or
"class instance variables", but I've yet to experience any problems
with class variables.

I think they have different purposes, strengths and weaknesses, but I
wouldn't recommend not using class variables, so I'm curious if I'm
missing some problem with them.

···

On Oct 18, 2:44 am, "Robert Klemme" <shortcut...@googlemail.com> wrote:

2007/10/18, Brian Adkins <lojicdot...@gmail.com>:
> On Oct 17, 4:10 pm, Perry Smith <p...@easesoftware.com> wrote:
> > I am using this technique for class instance variables:
> Just out of curiosity, why do you want a "class instance variable"
> instead of a class variable?

Probably because class variables have @@various issues as has
discusses before. I would also recommend to not use them.

Hi --

I am using this technique for class instance variables:

Just out of curiosity, why do you want a "class instance variable"
instead of a class variable?

Probably because class variables have @@various issues as has
discusses before. I would also recommend to not use them.

What issues have you experienced with them to cause you to not
recommend them? I rarely have a need for either class variables or
"class instance variables", but I've yet to experience any problems
with class variables.

I think they have different purposes, strengths and weaknesses, but I
wouldn't recommend not using class variables, so I'm curious if I'm
missing some problem with them.

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. 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.

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.

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.

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 :slight_smile: This is
one of the very few areas where I dissent strongly from the way it's
designed.

David

···

On Fri, 19 Oct 2007, Brian Adkins wrote:

On Oct 18, 2:44 am, "Robert Klemme" <shortcut...@googlemail.com> > wrote:

2007/10/18, Brian Adkins <lojicdot...@gmail.com>:

On Oct 17, 4:10 pm, Perry Smith <p...@easesoftware.com> wrote:

--
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!

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. 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 even that is squirrely. Visibility depends on sequence of
appearance, watch carefully, my fingers will ever leave my hands! <G>

class A
  @@x = "A"

  def self.show_x
    @@x
  end
end
      A.show_x # => "A"

class B < A
end
      B.show_x # => "A"

class B
  @@x = "B" # !> already initialized class variable @@x
end
      B.show_x # => "B"
      A.show_x # => "B"

class C
end

class D < C
  @@x = "D"
  def self.show_x
    @@x # !> class variable @@x of C is overridden by D
  end
end
    D.show_x # => "D"

class C
  @@x = "C"
  def self.show_x
    @@x
  end
end
   D.show_x # => "D"
   C.show_x # => "C"

class D
  @@x = "Blorp" # !> class variable @@x of C is overridden by D
end
D.show_x # => "Blorp"
C.show_x # => "C"

That sums up my views. Just so you know: I love Ruby madly :slight_smile: This is
one of the very few areas where I dissent strongly from the way it's
designed.

Amen, brother!

···

On 10/18/07, David A. Black <dblack@rubypal.com> wrote:

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

My gut says that code that utilizes class variables can always be
refactored to use class instance variables and perhaps some accessor
methods and the result will be equal or better to the original
class variable code.

I say ditch class variables all together.

Gary Wright

···

On Oct 18, 2007, at 1:22 PM, David A. Black wrote:

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.

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 :slight_smile: 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? :wink:

a @ http://codeforpeople.com/

···

On Oct 18, 2007, at 11:22 AM, David A. Black wrote:
--
it is not enough to be compassionate. you must act.
h.h. the 14th dalai lama

Well, I have to agree there are some odd things about Ruby's class variables, and they're not terribly useful most of the time, but in the cases where they are useful, they are useful.
Unless you need to count the number of instantiations of a class, I can't imagine what else to use them for.
But perhaps this kind of counter of class instantiations ( minus GC'd instances ) should be built-in to all Ruby classes and accessible via a method. Or at least the ability to create that count without using class variables proper.
Then again, is it that useful?
It is when it is needed.

I do think all the books should generally make a note that most folks will rarely need or want to use class variables.
Then each book should explicitly state that instance vars are what you will normally want to use day to day.

In the case of subclasses and so forth, choosing where you want to have a class variable is a design issue.
While OOP is easy to learn and understand, it is not easy to become good at designing classes. I know. I'm still not good at it.

Hi --

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

I think we're defining encapsulation differently. I don't mean that no
two objects should ever share any kind of data; rather, it's that
class variables don't play nicely with the system of which they are
part. I know about the "singleton" non-singletons... but at least
that's implemented in terms of inheritance (so really only the
terminology is at stake). I can see what a subclass has to do with its
parent class, especially given Matz's point that inheritance in Ruby
is mostly about "shared implementation". I find automatic variable
sharing between classes and instances much more problematic,
especially given the fact that classes are first-class objects (which
leads to all the problems with @@vars obscuring @vars, conceptually at
least).

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,

It's not a contest, though :slight_smile: It's possible that constants are
well-designed and class variables aren't, even if they share certain
behaviors. Actually, I'd add constants to the list of things, along
with instance variables, that can do most of what people usually use
class variables for.

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 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

OK... but I don't think we have to choose between (a) no two objects
ever sharing anything, and (b) deciding that some objects share some
things so we might as well give up trying to differentiate among
different cases. It's possible that mixins are well-designed and class
variables aren't, even if both of them involve, described at a very
high level, tearing down barriers between bits of code.

The sense I get from class variables is of quasi-globalness. I don't
get that sense when I include a mixin; I actually don't think it's the
same in either kind or degree.

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.

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 :slight_smile:

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.

"Clearly evil" works for me :slight_smile:

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 :slight_smile: 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

I don't think it would be such a disaster to have to say "|| self.class.bufsize". It would certainly be worthwhile tradeoff for
all the other problems.

  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.

(I'm happier with an equal-sign but I won't press the point :slight_smile:

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

[code snipped]

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.

I'm still happier with class objects playing in the same ballpark as
other objects, when it comes to per-object state. Set up, if desired,
a way for other objects to get at the state, and then have the other
objects send you messages. It's all about where one thinks the
special-case horizon should be, I guess.

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.

I'm not saying they should. I'm saying I'd like it if class variables
did :slight_smile: It's not a one-size-fits-all argument about misunderstood Ruby
features; it's specifically about class variables.

David

···

On Fri, 19 Oct 2007, ara.t.howard wrote:

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

--
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!

ara.t.howard wrote:

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

But this still works with ruby1.9! And it works in subclasses too. As long as @@bufsize is within the lexical context of Parser, it works just like 1.8. The difference is only if you try to use @@bufsize within the (lexical) scope of a subclass.

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!).

The main reason, I've never been completely comfortable with the Ruby
conflation of singleton class and metaclass. Or maybe it's the
conflation of singleton methods and class methods.

Seems to me that singleton methods SHOULD only be applicable to a
single object. A singleton class of a non-class is constrained to
containing only singleton methods in that sense, because it can't be
subclassed. A singleton class of a class is not. It's actually the
class that's the singleton here in that it's the only allowed instance
of its, dare I say it, metaclass.

But I digress.

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.

Agreed.

Inheritance is a power tool, valuable and sometimes dangerous. Did I
mention that it's valuable!

> 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.

I'm not sure that I totally agree here. There might well be class
methods which the class doesn't/shouldn't expose even to its
instances.

Perhaps there are use cases for a fourth visibility (in addition to
public, protected, and private) which makes a method visible to
instances, between public and protected.

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

Yes.

> 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.

I understand what you're saying Ara, but it's a little hard to grasp
because there really isn't anything which reifies 'a class hierarchy'.
In reality a class variable is associated with a class, which of
course is the root of a class hierarchy, but the way they are
implemented, it really means they get associated with a kind of
snapshot of the hierarchy as it existed at the time the class variable
was defined. I say this by way of explaining the problems of defining
a class variable in a superclass, AFTER a subclass has already defined
a class variable with the same name.

This is one instance of a small set of curiosities in Ruby due to
problems in re-building the runtime structures when certain
inheritance related changes occur. To me it seems to be similar to
the problems with the semantics of module re-inclusion.

Now I'm not sure that Matz was directly inspired by Smalltalk in
coming up with class variables, but given my background I tend to
think so. Ruby class variable have a lot in common with Smaltalk's
certainly in terms of inheritance and visibility in both class and
instance methods. Assuming he was...

One of the biggest differences (and I'd say for the most part it's an
improvement) between Ruby and Smalltalk is that in Smaltalk variables
are declared, whereas in Ruby they are defined in the process of
expression parsing/execution.

In Smalltalk, you declare a class with something like

   Object subclass: #Foo
                instanceVariableNames: 'instVar'
                classVariableNames: 'ClassVar'
                classInstanceVariableNames: 'classInstVar'
                poolDictionaries: 'PoolDict'

And the compiler uses these declarations when compiling a method. In
Smalltalk instance variables and class instance variables can be bound
to a slot at a fixed offset from the begining of the instance, or
class. Class variables can be bound to the value slot in a dictionary
associated with the class. I'll ignore pool dictionaries, they serve
some of the purposes of the name space aspect of modules.

The compiler searches up the hierarchy to find inherited class
variables, and the methods for manipulating the classVariableNames
list of a class validate that a conflict can't be created. Changing
the class declaration in Smalltalk triggers a recompilation of all
methods of the class and its subclasses.

Ruby substitutes run-time binding binding of variables, rather than
being at a fixed offset, ruby instance (and class instance) variables
are bound to a value slot in a hash associated with the instance or
class, class variables are bound to a hash as well (the last time I
looked it was the same hash, which works because the key contains the
sigil, so the keys :@instance_var, and :@@class_var can both be in the
hash, reflection methods like Object#instance_variables filter their
results to hide this implementation. Note also that this description
is from my memory of reading the MRI 1.8.x code, other Ruby 1.8
implementations might well use different implementation techniques but
should have the same semantics.

So what was my point here? Oh yes. I was talking about what happens
when you make certain changes to the inheritance structure. If we
had:

class A
end

class B < A
     @@cv = 42
end

And then later
class A
    @@cv = 57
end

Ruby currently at most warns about a conflict then goes ahead and adds
a new class variable to A, leaving the existing one in C.

I think that the change in 1.9 was motivated by this anomaly, by doing
away with the inheritance of class variables we avoid the surprise.
On the other hand, as you point out below, the baby might be being
thrown out with the bath water!

It seems to me that another solution would be to simply remove the
class variable from a subclass when a superclass subsequently creates
one with the same name. Sure B's view of @@cv would change from 42 to
57, but that's consistent with the intended semantics, I think.

On the other hand, there might be subtleties I can't yet fathom, much
like I still don't understand why 1.9 changed the semantics of:

module M
    def meth
        "M"
    end
end

class A
   include M
end

class B < A
   def meth
         "B"
   end
end

class C
    include M
end

C.new.meth

So that in 1.9 this used to result in "M" but then they changed it
back to the 1.8 semantics which ignore the re-inclusion and results in
"B".

> 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.

i think that the problem should be dissected, it's really two problems:

   1) Ruby class variables look too much like instance variables
because of syntax @@ vs @
   2) The Ruby class variable implementation has a few rough edges.

The first problem makes me tend to agree that it would have been
better to choose another sigil for denoting class variables, although
this would seem to have a pretty sizable cost in backward
compatibility.

The second problem would seem to be fixable, at some cost to backward
compatibility, but 1.9 has already taken one path at fixing it.

>
> 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.

I guess that the only difference between class variables and class
instance variables in 1.9 is that the former are visible in instance
methods.

It seems to me that the baby is in the bathwater here, the baby being
uses which rely on inheritance of class variables.

It might be interesting to see what happens when rails steps up to
ruby 1.9. It appears to use class variables pretty extensively. I'm
not sure how much it relies on class variable inheritance though.

> That sums up my views. Just so you know: I love Ruby madly :slight_smile: 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

.. Long example justifying inheritable class variables snipped.

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.

Not much to disagree with here.

An interesting side note. In Smalltalk, the declaration of variables
doesn't initialize them. Conventionally, class variables are
initialized in a class method called initialize. I'm a bit rusty on
this but IIRC this is something which has to be done manually after
defining the method and before instantiating any instances of the
class.

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

To summarize what I've said, I think it's a combination of the
semantics and the implementation.

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.

Amen.

pss. encapsulation is vastly overrated. when is that last time you
used 'protected' in any ruby code? :wink:

Careful, Ara, the thought police are lurking! <G>

···

On 10/19/07, ara.t.howard <ara.t.howard@gmail.com> wrote:

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

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

I think we're defining encapsulation differently. I don't mean that no
two objects should ever share any kind of data; rather, it's that
class variables don't play nicely with the system of which they are
part. I know about the "singleton" non-singletons... but at least
that's implemented in terms of inheritance (so really only the
terminology is at stake). I can see what a subclass has to do with its
parent class, especially given Matz's point that inheritance in Ruby
is mostly about "shared implementation". I find automatic variable
sharing between classes and instances much more problematic,
especially given the fact that classes are first-class objects (which
leads to all the problems with @@vars obscuring @vars, conceptually at
least).

yeah i see that. i avoid them much of the time for those reasons. but, technically, doing something like this

   class C
     SHARED_WITH_ALL_SUBCLASSES_AND_INSTANCES =
   end

does the same. it's something worth considering.

and constants and singleton methods.... of course class singleton methods,

It's not a contest, though :slight_smile: It's possible that constants are
well-designed and class variables aren't, even if they share certain
behaviors. Actually, I'd add constants to the list of things, along
with instance variables, that can do most of what people usually use
class variables for.

sort of. if you need state to be inherited you can use constants. if you want true class singleton state that is settable you can use class instance variables. if you want state that is settable AND inherited the simplest option at the moment are class @@variables. the way they mix into instances, i would agree is confusing, but there really aren't any other *simple* options for inheriting state in classes

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

   class C
     @how_do_instances_get_at_this

     def initialize
       class << self.class
         def with_a_public_accessor() @how_do_instances_get_at_this end
       end

       self.class.with_a_public_accessor
     end

so the typical pattern with class instance variables is to expose them publicly and this may break encapsulation iff the information exposed is best left internal to the class and it's instances

OK... but I don't think we have to choose between (a) no two objects
ever sharing anything, and (b) deciding that some objects share some
things so we might as well give up trying to differentiate among
different cases. It's possible that mixins are well-designed and class
variables aren't, even if both of them involve, described at a very
high level, tearing down barriers between bits of code.

The sense I get from class variables is of quasi-globalness. I don't
get that sense when I include a mixin; I actually don't think it's the
same in either kind or degree.

yeah the fact that instances see them does indeed make them seem quasi global - but the lack of another inherited class state mechanism is a show stopper when it comes to declaring them useless and poorly designed. that's critical functionality in some object hierarchies.

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 :slight_smile:

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

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. 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.

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

I don't think it would be such a disaster to have to say "|| self.class.bufsize". It would certainly be worthwhile tradeoff for
all the other problems.

i disagree - if you do that you've designed a class that cannot be subclassed: as that line will return 'nil' in those subclasses. if you do that you should be using a singleton object or module - not a class - to model your problem domain.

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

[code snipped]

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.

I'm still happier with class objects playing in the same ballpark as
other objects, when it comes to per-object state. Set up, if desired,
a way for other objects to get at the state, and then have the other
objects send you messages. It's all about where one thinks the
special-case horizon should be, I guess.

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. i guess i just don't think that inheritance/setup of class state is something that people should be expected to roll on their own in a language as powerful as ruby - it can get quite complex when modules enter the picture too. i'd rather entrust matz to solved the problem generically :wink:

I'm not saying they should. I'm saying I'd like it if class variables
did :slight_smile: It's not a one-size-fits-all argument about misunderstood Ruby
features; it's specifically about class variables.

oh i understand that david - no worries. what i'm saying is simply that i've probably designed as many complex ruby class hierarchies as anyone else out there and i've solved the class state sharing issue a whole bunch of times in different ways: sometimes using 'inherited', sometimes by factoring things out into modules, and sometimes using @@variables and none of them are perfect. my experience has lead me to think that any discussion of the evils of class variables (and i've said they are evil on this list too!) shouldn't be outside the context of how to *better* share and initialize state between parent and child classes because it's an important feature in an oop language - in short, it's a red herring.

cheers.

a @ http://codeforpeople.com/

···

On Oct 19, 2007, at 5:09 AM, David A. Black wrote:
--
share your knowledge. it's a way to achieve immortality.
h.h. the 14th dalai lama

yup. i haven't used that in anger so i really don't know if it'll be helpful or even more confusing - at least state can still be inherited, even with a somewhat crippled impl.

time will tell!

cheers.

a @ http://codeforpeople.com/

···

On Oct 19, 2007, at 9:39 AM, Daniel DeLorme wrote:

But this still works with ruby1.9! And it works in subclasses too. As long as @@bufsize is within the lexical context of Parser, it works just like 1.8. The difference is only if you try to use @@bufsize within the (lexical) scope of a subclass.

--
it is not enough to be compassionate. you must act.
h.h. the 14th dalai lama

So what was my point here? Oh yes. I was talking about what happens
when you make certain changes to the inheritance structure. If we
had:

class A
end

class B < A
     @@cv = 42
end

And then later
class A
    @@cv = 57
end

Ruby currently at most warns about a conflict then goes ahead and adds
a new class variable to A, leaving the existing one in C.

Ok, you've used a similar example multiple times now, so my curiosity
is getting the best of me - do you actually code this way, or are you
trying to come up with a contrived example to show the alleged
problems with class variables? Wouldn't you typically initialize the
class variable in the "superest" class only?

...
On the other hand, there might be subtleties I can't yet fathom, much
like I still don't understand why 1.9 changed the semantics of:

module M
    def meth
        "M"
    end
end

class A
   include M
end

class B < A
   def meth
         "B"
   end
end

class C
    include M
end

C.new.meth

So that in 1.9 this used to result in "M" but then they changed it
back to the 1.8 semantics which ignore the re-inclusion and results in
"B".

Should 'class C' be 'class C < B' ?

···

On Oct 19, 12:22 pm, "Rick DeNatale" <rick.denat...@gmail.com> wrote:

On 10/19/07, ara.t.howard <ara.t.how...@gmail.com> wrote:
> On Oct 18, 2007, at 11:22 AM, David A. Black wrote: