ruby picture

RCR 185: @@_classInstanceVar and @_restrictedInstanceVar

Submitted by coreywangler (Wed Jan 07 16:01:21 UTC 2004)

Abstract

Prevent @instanceVariable initialization bug by renaming @classInstanceVar to @@_classInstanceVar.

Introduce @_restrictedInstanceVar to keep the meaning of added underscore consistent.

Problem

Current @classInstanceVariables confuse the programmer due to identical naming to a normal @instanceVariable, especially where the nubie mistakenly puts an initialization of an @variable outside of an instance method (making it a @classInstanceVariable instead of what they assumed would be a normal @instanceMethod).

    
  1. probable initialization bug gets introduced in this code
class Foo
  @a = 123   # (1) class instance var initialized
  def foo
    p @a     # (2) 'normal' instance var accessed ...nil not 123
  end
end

Proposal

Use modified syntax @@_classInstanceVariable instead of @classInstanceVariable. This means that @variables will only be seen in instance methods.

Add syntax @_restrictedInstanceVariable, meaning an instance variable that is not accessible to subclasses. This is something Matz is already considering for Ruby 2. This is included in this proposal to ensure consistent meaning for the adding of a trailing underscore to the @ or @@ prefix (meaning "internal use" or "hidden").
@@classVariable
     * one value shared by all instances of the class
     * visible in instance methods
     * acts like a global variable for the class/module

@@_classInstanceVariable #<=-modified syntax
     * instances of the class each get their own value to use
     * not visible in instance methods
     * could think of it as a "scratch variable" for use by class methods
     * think of underscore as meaning "internal use", "hidden"

@instanceVariable
     * can be accessed by subclasses

@_restrictedInstanceVariable #<=-new syntax
     * not accessible by subclasses
     * think of underscore as meaning "internal use", "hidden"
Note that (with the renaming of @classInstanceVar to @@_classInstanceVar) @variables cannot be initialized or used outside of instance methods, and should give an error message like "an @variable can only be used within instance methods" if such use is attempted.

Think of @@ meaning "used in class body and class methods"
Think of @ meaning "used *only* in instance methods"
Think of underscore as meaning "internal use", or "hidden in some way"
class Foo
  # not allowed - use a @@_classInstanceVariable here instead if 
  #   that is the intention
  # error message should say something like 
  #   "@variable must be initialized within an instance method"
  @variable = 0    #produce an error message
  # initialize a class variable, accessible within both 
  #     class methods and instance methods of the class
  @@exampleClassVariable = 880
  # initialize a class instance variable,
  #     not accessible by instance methods
  @@_exampleClassInstanceVariable = 770
  # class method
  def Foo.setExampleClassVariable(value)
    @@exampleClassVariable = value  
  end
  # another class method
  def Foo.setExampleClassInstanceVariable(value)
    @@_exampleClassInstanceVariable = value  
  end
  def initialize
    # initialize an instance variable, accessible within
    #   instance methods of class and subclasses
    @exampleInstanceVariable = 30
    # initialize a "restricted instance variable", 
    #     not accessible by subclasses
    @_exampleRestrictedInstanceVariable = 20
    # modify a class variable
    @@exampleClassVariable += 1
  end  
end

Analysis

Advantages:
Prevents the @instanceVariable initialization bug.
Clarifies where @@ and @ are to be used in the code.
Class body and class methods only have @@ or @@_ in them.
All @ vars are initialized and used within instance methods.
@@_classInstanceVariables typically not used much, so uglier is better :D

Disadvantages:
Existing usage of @classInstanceVar will need renaming to @@_classInstanceVar, although the disallowing of "@variables" in class body and class methods will show what variables need to be renamed at parse time.

Implementation

Changes in language.
ruby picture
Comments Current voting

In Ruby, classes are object, no exception. This is very important principle. Your proposal may hinder learning of this principle.

Maybe warnings to the instance variable assignments in the class body might solve the problem very nicely without modifying language syntax.

- matz.

Class instance variable is a special case

Class instance variables are a special case, because those can only be used in class methods and are not visible in instance methods.

What I am proposing is a re-think on what @@ means...
"@@ is associated with class implementation".
"@ is associated with instance implementation."


I also thought about suggesting @@_@classInstanceVariable (instead of the original suggested @@_classInstanceVariable). This would make it clear that it is both

  @@_@classInstanceVariable
 "@@    associated with class", and _also_ <br>
 "  _@  associated with an instance: an instance of a class in this case"

Maybe I should resubmit the RCR with that, as I like it better after considering your comment.

Another thing to consider is how much this feature of the language (class instance variables) is used. A lot of programmers would never touch such an animal, because it is an advanced concept used for meta-programming.

I am guessing that most usage would be of the plain @@classVariable, and you would rarely see @@_@classInstanceVariable. Such notation is a bit uglier, but ensures that the programmer gets exactly what they ask for (less surprise! -- I didn't mention POLS ...doh, wait I just did ;)


Strongly opposed 0
Opposed 0
Neutral 0
In favor 0
Strongly advocate 0
ruby picture

This RCR has been superseded by RCR 186.

ruby picture

Powered by .