Class instance variables, class variables and constants


#1

Hello,

Thanks to the code in attach, I’ve figured out what is now completely
obvious to me:

CLASS VARIABLE (@@something)

  • Inherited by subclasses
  • SAME ALLOCATION: If it’s changed in Child, then it will change in
    Parent

CONSTANTS (Something)

  • Inherited by subclasses
  • PRIVATE ALLOCATION: If it’s changed in Child, it will NOT change in
    parent

CLASS INSTANCE VARIABLES (@something)

  • NOT Inherited by subclasses. They will simply be nil. Scope = Class
  • DIFFERENT ALLOCATION: If it’s changed in Child, it will NOT change
    in parent

I am sending this email to the mailing list so that if some Ruby
newbie has the same problem with variable scope, they might find this
email (and find it useful).

David A. Black wrote:

“I think Matz is planning to change class variables in 2.0 so that they
are class/module scoped rather than hierarchy scoped.”

But wouldn’t it make class variables (@@something) the same as class
instance variables (@something)?

Here’s the code I used to figure things out:


#!/usr/local/bin/ruby -w

class Outer
@@class_var=10
GlobalVar=100
@civ=1000

     class Second < Outer

             @@class_var=11
             GlobalVar=101
             @civ=1001

             def Second::class_var
                     @@class_var
             end

             def Second::class_var=(what)
                     @@class_var=what
             end

             def Second::civ
                     @civ
             end

             def Second::civ=(what)
                     @civ=what
             end


     end

     def Outer::class_var
             return @@class_var
     end

     def Outer::class_var=(what)
             @@class_var=what
     end

     def Outer::civ
             @civ
     end

     def Outer::civ=(what)
             @civ=what
     end

end

class Third < Outer

     def self::class_var
             return @@class_var
     end

     def Third::class_var=(what)
             @@class_var=what
     end

     def Third::class_var
             @@class_var
     end

     def Third::class_var=(what)
             @@class_var=what
     end

     def Third::civ
             @civ
     end

     def Third::civ=(what)
             @civ=what
     end

end

puts “Outer”
p Outer::class_var
p Outer::GlobalVar
p Outer::civ
puts “Outer::Second”
p Outer::Second::class_var
p Outer::Second::GlobalVar
p Outer::Second::civ
puts “Third”
p Third::class_var
p Third::GlobalVar
p Third::civ
puts
puts

Outer::Second::class_var=13
Outer::Second::GlobalVar=103
Outer::Second::civ=1003

puts “Outer”
p Outer::class_var
p Outer::GlobalVar
p Outer::civ
puts “Outer::Second”
p Outer::Second::class_var
p Outer::Second::GlobalVar
p Outer::Second::civ
puts “Third”
p Third::class_var
p Third::GlobalVar
p Third::civ
puts
puts

Third::class_var=14
Third::GlobalVar=104
Third::civ=1004

puts “Outer”
p Outer::class_var
p Outer::GlobalVar
p Outer::civ
puts “Outer::Second”
p Outer::Second::class_var
p Outer::Second::GlobalVar
p Outer::Second::civ
puts “Third”
p Third::class_var
p Third::GlobalVar
p Third::civ
puts
puts

Just checking…

p Third::Second::class_var
p Third::Second::GlobalVar
p Third::Second::civ


#2

On Mon, 20 Feb 2006 15:22:04 +0100, Tony M. removed_email_address@domain.invalid wrote:

CONSTANTS (Something)

  • Inherited by subclasses
  • PRIVATE ALLOCATION: If it’s changed in Child, it will NOT change in
    parent

CLASS INSTANCE VARIABLES (@something)

  • NOT Inherited by subclasses. They will simply be nil. Scope = Class
  • DIFFERENT ALLOCATION: If it’s changed in Child, it will NOT change in
    parent

But there is more fun when singleton classes get involved:

class A
@@var = :A
C = :CA
end

class B
@@var = :B
C = :CB

a = A.new
class ::A
p [@@var, C] # => [:A, :CA]
def foo
[@@var, C]
end
end
def a.bar
[@@var, C]
end
class << a
p [@@var, C] # => [:B, :CB]
def baz
[@@var, C]
end
end
p a.foo # => [:A, :CA]
p a.bar # => [:B, :CB]
p a.baz # => [:B, :CB]
p [@@var, ::a::C, C, class << a;C;end] # => [:B, :CA, :CB, :CB]
class << a
@@var = :ASing # this changes B’s @@var [*]
C = :CASing # this creates a new C for a’s sing. class
end
p [@@var, ::a::C, C, class << a;C;end] # => [:ASing, :CA, :CB,
:CASing]
p a.foo # => [:A, :CA]
p a.bar # => [:ASing, :CB]
p a.baz # => [:ASing, :CASing]
end

Some points:

  • singleton classes don’t have their own class variables, but they can
    have their own constants
  • constant and class var lookup use the lexical scope, so it depends
    “where” you do something (that’s why bar’s C and baz’s C are different)
  • (lexical) singleton-class-scopes are skipped when accessing class vars
    (that’s why [*] changes B’s @@var and not A’s @@var)

I hope that helps and doesn’t totally confuse you :wink:

Dominik


#3

Hi,

Some points:

  • singleton classes don’t have their own class variables, but they
    can have their own constants
  • constant and class var lookup use the lexical scope, so it
    depends “where” you do something (that’s why bar’s C and baz’s C
    are different)
  • (lexical) singleton-class-scopes are skipped when accessing class
    vars (that’s why [*] changes B’s @@var and not A’s @@var)

I hope that helps and doesn’t totally confuse you :wink:

OK. One hour later, this is became clear…
I’d write the points above in a different order:

  • singleton classes can have their own constants

  • singleton classes don’t have their own class variables. (Lexical)
    singleton-class-scopes are skipped when accessing class vars

  • constant and class variable lookup use the lexical scope, so it
    depends “where” you do something

Now… I do have a question. On one hand, I really, really want to
know all these fine details. That’s just my nature.
However, in this case, I must ask: is this going to be useful at
any point in time?
When would you want to set a constant for a singleton class?

The rest makes perfect sense to me: a singleton class could
realistically need access a class variable. And I realise that I need
to know that constant and class variable lookup use the lexical
scope. But… singleton constants…?

Just curious!

Merc.


#4

DÅ?a Pondelok 20 Február 2006 23:35 Tony M. napísal:

When would you want to set a constant for a singleton class?

Hardly ever? It’s not like you need more instances to always get the
same
value.

David V.


#5

DÅ?a Pondelok 20 Február 2006 15:22 Tony M. napísal:

“I think Matz is planning to change class variables in 2.0 so that they
are class/module scoped rather than hierarchy scoped.”

But wouldn’t it make class variables (@@something) the same as class
instance variables (@something)?

Nope. Class variables could still be “inherited”, but they wouldn’t
clobber
stuff up the hierarchy if modified.

David V.


#6

Hi –

On Tue, 21 Feb 2006, Dominik B. wrote:

Some points:

  • singleton classes don’t have their own class variables, but they can have
    their own constants

There’s an interesting discussion of this in an earlier thread; see
especially:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/65527

David


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light (http://www.rubypowerandlight.com)

“Ruby for Rails” chapters now available
from Manning Early Access Program! http://www.manning.com/books/black