tags:

views:

74

answers:

3

I know that some say the @@class_var syntax should be avoid in Ruby and should use the @instance_var in the class' scope instead ...

def MyClass
 @@bad_class_var # Should not do this.
 @good_class_var # Should do this.
end

My question is why the @@ notation is frowned upon in Ruby?

A: 

First of all there is a difference between

@@var

and

@var

@@var is a class variable that is the same in all instances of a class. @var is an instance variable that is bound to an instance of a class.

Little example:

class MyClass
  @inst_var
  @@cls_var

  def initialize(a, b)
    @inst_var = a
    @@class_var = b
  end
end

myobject1 = MyClass.new(1, 2)
puts myobject1.inst_var # gives 1
puts myobject1.cls_var # gives 2

myobject2 = MyClass.new(3, 4)
puts myobject2.inst_var # gives 3
puts myobject2.cls_var # gives 4
puts myobject1.inst_var # gives 1
puts myobject1.cls_var # gives 4!!!

A class variable in Ruby is like a static variable in C#. Hope this helps a bit in understanding the difference.

Aurril
This did not answer the question. The `@inst_var` in your second line does nothing.
sepp2k
Little typo. I think it answers the question as it states that the one syntax is not equal to the other one. I have yet to hear that class variables are "frowned upon in Ruby".
Aurril
@Aurril: No you completely missed the point. If you do `class MyClass; @inst_var = 42; def self.inst_var() @inst_var end end` you'll see that it is in fact perfectly possible to use instance variables in the class' scope as a replacement for class variables.
sepp2k
@sepp2k: In your example you are using a class method to work around using a class variable. Of course you can do it that way, but why should you?
Aurril
@Aurril: "In your example you are using a class method to work around using a class variable." Yes, that's what "using an instance variable in the class' scope" means. "But why should you?" This is exactly the OP's question. I hope I answered it in my answer.
sepp2k
+6  A: 

Class variables are often maligned because of their sometimes confusing behavior regarding inheritance:

class Foo
  @@foo = 42

  def self.foo
    @@foo
  end
end

class Bar < Foo
  @@foo = 23
end

Foo.foo #=> 23
Bar.foo #=> 23

If you use class instance variables instead, you get:

class Foo
  @foo = 42

  def self.foo
    @foo
  end
end

class Bar < Foo
  @foo = 23
end

Foo.foo #=> 42
Bar.foo #=> 23

This is often more useful.

sepp2k
+1  A: 

Be careful; class @@variables and instance @variables are not the same thing.

Essentially, when you declare a class variable in a base class, it’s shared with all subclasses. Changing its value in a subclass will affect the base class and all of its subclasses all the way down the inheritance tree. This behavior is often exactly what’s desired. But equally often, this behavior is not what was intended by the programmer, and it leads to bugs, especially if the programmer did not originally expect for the class to be subclassed by someone else.

From: http://sporkmonger.com/2007/2/19/instance-variables-class-variables-and-inheritance-in-ruby

NullUserException