Class variables and Constants

Hello people,

what is the actual difference between class variables and constants?

If I write:

···

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

class TonyCantCode
         @@internal=10

         def TonyCantCode::something
                 return @@internal
         end

         def TonyCantCode::something=(what)
                 @@internal=what
         end

end

class TonyReallyCantCode
         Something=20
end

p TonyCantCode::something
p TonyReallyCantCode::Something

TonyCantCode::something=30
TonyReallyCantCode::Something=40

p TonyCantCode::something
p TonyReallyCantCode::Something
------------------------------------------------

I get a warning about changing a constant, PLUS I called the method TonyCantCode::something so that I didn't have to use the brackets at the end.

BUT... as far the the scope is concerned, they do seem to be very. very similar.
As far as I can see:

* Constants would be referenced mainly from the OUTSIDE of the class. For example, if TonyReallycantCode::Something was something very meaningful to the USERS of TonyReallyCantCode.

* Class variables would be used mainly from WITHIN the class. Yes, it is possible to create accessors, but they might not be necessary.

This is what I worked out. Now the question is: is all the above correct?

BYE!

Merc.

Dear Tony,

[OK, I am gonna answer myself]

The main difference actually makes a lot of sense.

If you change a class constant (which you shouldn't do), then all of the classes which inherited from it will see their constant changed as well.

Class variables, on the other hand, are allocated for the class itself. This means that each class (or sub-class) will have its own class variables.

Here is some code to clarify the concept.

···

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

class TonyCantCode
         @@internal=10

         def TonyCantCode::something
                 return @@internal
         end

         def TonyCantCode::something=(what)
                 @@internal=what
         end

end

class TonyReallyCantCode
         Something=20
end

class TonyCantCode2 < TonyCantCode
end

class TonyReallyCantCode2 < TonyReallyCantCode
         Something=20
end

p TonyCantCode::something
p TonyReallyCantCode::Something

TonyCantCode::something=30
TonyReallyCantCode::Something=40

p TonyCantCode::something
p TonyReallyCantCode::Something

p TonyCantCode2::something
p TonyReallyCantCode2::Something

RESULT:

$ ./vars.rb
10
20
./vars.rb:33: warning: already initialized constant Something
30
40
30
20 <-- !!!

---------------------------------------------------

Bye!

Merc.

On 20/02/2006, at 6:05 PM, Tony Mobily wrote:

Hello people,

what is the actual difference between class variables and constants?

If I write:

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

class TonyCantCode
        @@internal=10

        def TonyCantCode::something
                return @@internal
        end

        def TonyCantCode::something=(what)
                @@internal=what
        end

end

class TonyReallyCantCode
        Something=20
end

p TonyCantCode::something
p TonyReallyCantCode::Something

TonyCantCode::something=30
TonyReallyCantCode::Something=40

p TonyCantCode::something
p TonyReallyCantCode::Something
------------------------------------------------

I get a warning about changing a constant, PLUS I called the method TonyCantCode::something so that I didn't have to use the brackets at the end.

BUT... as far the the scope is concerned, they do seem to be very. very similar.
As far as I can see:

* Constants would be referenced mainly from the OUTSIDE of the class. For example, if TonyReallycantCode::Something was something very meaningful to the USERS of TonyReallyCantCode.

* Class variables would be used mainly from WITHIN the class. Yes, it is possible to create accessors, but they might not be necessary.

This is what I worked out. Now the question is: is all the above correct?

BYE!

Merc.

Hi --

Dear Tony,

[OK, I am gonna answer myself]

The main difference actually makes a lot of sense.

If you change a class constant (which you shouldn't do), then all of the classes which inherited from it will see their constant changed as well.

Class variables, on the other hand, are allocated for the class itself. This means that each class (or sub-class) will have its own class variables.

Here is some code to clarify the concept.

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

class TonyCantCode
      @@internal=10

      def TonyCantCode::something
              return @@internal
      end

      def TonyCantCode::something=(what)
              @@internal=what
      end

end

class TonyReallyCantCode
      Something=20
end

class TonyCantCode2 < TonyCantCode
end

class TonyReallyCantCode2 < TonyReallyCantCode
      Something=20
end

p TonyCantCode::something
p TonyReallyCantCode::Something

TonyCantCode::something=30
TonyReallyCantCode::Something=40

p TonyCantCode::something
p TonyReallyCantCode::Something

p TonyCantCode2::something
p TonyReallyCantCode2::Something

RESULT:

$ ./vars.rb
10
20
./vars.rb:33: warning: already initialized constant Something
30
40
30
20 <-- !!!

Have you tried this?

    class A
      @@var = 10
      def self.var
        @@var
      end
    end

    class B < A
      @@var = 20
    end

    p A.var

:slight_smile:

David

···

On Mon, 20 Feb 2006, Tony Mobily wrote:

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

Hi,

Have you tried this?

   class A
     @@var = 10
     def self.var
       @@var
     end
   end

   class B < A
     @@var = 20
   end

   p A.var

:slight_smile:

AAAAAAAHHHHHHHHH!!!!!!!!!!!!
I've been playing with this the whole night. I am not gonna stop until I've finished writing a clear document that explains absolutely everything.

Merc.

Hi --

Hi,

Have you tried this?

  class A
    @@var = 10
    def self.var
      @@var
    end
  end

  class B < A
    @@var = 20
  end

  p A.var

:slight_smile:

AAAAAAAHHHHHHHHH!!!!!!!!!!!!
I've been playing with this the whole night. I am not gonna stop until I've finished writing a clear document that explains absolutely everything.

I think Matz is planning to change class variables in 2.0 so that they
are class/module scoped rather than hierarchy scoped. Meanwhile,
here's another fun variant:

class A
end

class B < A
   @@var = 10
   def self.var
     @@var
   end
end

class A
   @@var = 20
   def self.var
     @@var
   end
end

p A.var
p B.var

David

···

On Mon, 20 Feb 2006, Tony Mobily wrote:

--
David A. Black (dblack@wobblini.net)
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

Hi,

AAAAAAAHHHHHHHHH!!!!!!!!!!!!
I've been playing with this the whole night. I am not gonna stop until I've finished writing a clear document that explains absolutely everything.

I think Matz is planning to change class variables in 2.0 so that they
are class/module scoped rather than hierarchy scoped. Meanwhile,
here's another fun variant:

class A
end

class B < A
  @@var = 10
  def self.var
    @@var
  end
end

class A
  @@var = 20
  def self.var
    @@var
  end
end

p A.var
p B.var

The result is:

20
10

Oh dear... let me guess.
To start with, the class A doesn't have @@var defined. Class B is defined, and @@var is allocated. B will share @@var with all of its children. Then, A happened to be extended and @@var is allocated. It will share @@var with its children, but NOT B.
The compiler smells something fishy there, and says:

./p.rb:9: warning: class variable @@var of A is overridden by B

Which is what happens: effectively, the hierarchy rule is NOT going to be satisfied.

I love Ruby, but this is so error-prone it's not funny :expressionless:

Merc.

Dňa Pondelok 20 Február 2006 14:50 dblack@wobblini.net napísal:

> AAAAAAAHHHHHHHHH!!!!!!!!!!!!
> I've been playing with this the whole night. I am not gonna stop until
> I've finished writing a clear document that explains absolutely
> everything.

I tried to do Poor Man's Traits in Java using static fields. I feel your pain.

It's especially likely to cause initialization timing bugs - when I loaded the
page from the webapp after a server restart, everything worked fine - by some
strange coinkydink, the classes loaded earlier weren't used after they got
clobbered by the subclasses loaded earlier. Lossage ensued after a page
reload.

I think Matz is planning to change class variables in 2.0 so that they
are class/module scoped rather than hierarchy scoped. Meanwhile,
here's another fun variant:

class A
end

class B < A
   @@var = 10
   def self.var
     @@var
   end
end

class A
   @@var = 20
   def self.var
     @@var
   end
end

p A.var
p B.var

Oh dear. I do hope the change gets into 2.0, I can't wait for Java trolls to
ramble against it...

(Now don't tell anyone, but I have a hunch class instance variables actually
work like you'd expect in this case. I think.)

David Vallner

Hi --

Dňa Pondelok 20 Február 2006 14:50 dblack@wobblini.net 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. Meanwhile,
here's another fun variant:

class A
end

class B < A
   @@var = 10
   def self.var
     @@var
   end
end

class A
   @@var = 20
   def self.var
     @@var
   end
end

p A.var
p B.var

Oh dear. I do hope the change gets into 2.0, I can't wait for Java trolls to
ramble against it...

(Now don't tell anyone, but I have a hunch class instance variables actually
work like you'd expect in this case. I think.)

Basically a "class instance variable" is no different from any other
instance variable -- it just happens to belong to a class object. The
phrase has become commonplace, I guess, because it's sort of unclear
otherwise, when you talk about, say, "a class's instance variables",
whether you mean the class object's or the ones it is responsible for
providing for its own instances.

Anyway, instance variables of class objects do, indeed, provide
per-class (i.e., per-object-that-happens-to-be-a-class) state, which
class variables don't. I think the 2.0 change is going to be that
class variables will be like instance variables of a class, except
that they will be visible inside the class's instance methods.

David

···

On Tue, 21 Feb 2006, David Vallner wrote:

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails