Submitted by coreywangler (Wed Jan 07 23:01:04 UTC 2004)
class Foo
@a = 123 # (1) class instance var initialized def foo p @a # (2) 'normal' instance var accessed ...nil not 123 end
end
@@_@classInstanceVariable "@@ associated with class", and _also_ " _@ associated with an instance -- an instance of a class in this case"
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.
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
Comments | Current voting | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
This RCR supersedes RCR 185.
RCRchive copyright © David Alan Black, 2003-2005.
Powered by .
Note that class instance variable is a special case
(extracted from comment in superceded RCR185)
Class instance variables are a special case, because they can only be used in class methods and are not visible in instance methods.
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 ;)
- corey.
David Black:
The thing is, though... class instance variables are not a special case. Classes are, indeed, special objects in some respects, but not in this respect -- i.e., not when it comes to instance variables. It would be very anomalous to have a particular class of objects with its own syntax for instance variables.
I know that people find this confusing sometimes, but I honestly believe that they find it confusing literally because it is so simple: classes are objects, and an object can have instance variables. Anything beyond that becomes an extra convolution or special case; I'd rather keep it simple and force the issue so that people *have* to grasp it :-)
Withdrawing this RCR
Yeah, I have to agree with that. Now it is clear to me that @classInstanceVar is fine because we can segregate them from @instanceVar by restricting @classInstanceVar to within class methods.
Disallowing @classInstanceVar initialization in the class body (or at least giving a stern warning! ;) would make it more consistent with @instanceVar usage.
Cheers,
- corey.
Class body is a class method
I was considering if @classInstanceVar could be limited to use in only class methods, and finally came to the understanding that the class body is in fact a class method -- one that is sort of the class's equivalent to the instance's "initialize" method, because the class body is what is executed when the class is created. So having @classInstanceVariables initialized in the class body is really a logical thing.
Banning @classInstanceVariables from the class body would force their initialization into (other) defined class methods, which would need to be called from the class body. This would be an extra complication for the programmer to learn, and hence is not a good solution.
Renaming @classInstanceVar (e.g. to @@_@classInstanceVar as suggested by this RCR) would also be an extra complication, because it has been rightly pointed out that classes are also just another object and therefore should not have special syntax for their instance variables.
It would seem that this is a gotcha that needs to be there... a necessary complexity due to its elegant simpleness ;) -- but David probably said it better!
- corey.
An even simpler way to put it: at any given point in program execution, the instance variable @var belongs to the object 'self'. And when you do "class C", self is C. -- David (who has to figure out why comments on withdrawn RCRs are appearing twice :-)