From: Rick DeNatale Date: 2007-12-14T21:59:38+09:00 Subject: Re: C extension: can rb_ivar_set be used to set class variable? On 12/14/07, lianliming wrote: > Thanks for your reply! > > > No, use rb_cvar_set to set class variables. rb_ivar_set sets > > an instance variable of a class instance. I.E., > > > > class Foo > > @foo = "ivar" > > @@foo = "cvar" > > end > > Will the instance variable "@foo"'s value declared as the above > example can be referenced in an object of Class Foo? > > Please look at following example: > > class Foo > @foo = "ivar" > > def printFoo > puts @foo > end > end > > f=Foo.new > f.printFoo > ========> nil > > So now, I am curious to know, why the function rb_ivar_set allows > passing a "klass" as the first parameter to set value of a instance > variable which can't be referenced by its objects. rb_ivar_set takes an object as the first parameter. Classes are objects, and as such can have their own instance variables which are visible in class methods. These are called class instance variables, and are quite different from class variables. Being instance variables, class instance variables are only visible to methods of the object to which they are attached, which in the case of class instance variables would be class methods. There's also a subtlety to the Ruby object model which can be surprising to folks familiar with other OO languages. In many languages including Java, C++ and Smalltalk, one of the functions of a class is to serve as a template which maps the layout of the object in memory, in a manner analogous to a C struct, so that method code can reference instance variables by offset from the address of the instance. Ruby classes don't really "know" about the instance variables of their instances, since instance variables( actually all variables) aren't declared in Ruby. Instance variables get attached to an instance dynamically when a method is executed which mentions that instance variable. In fact different instances of the same class can have different sets of instance variables, and the set of instance variables of a particular object can change over time. Conceptually, and actually at least for Matz's Ruby Implementation, instance variables are resolved by accessing a per-instance internal hash table which maps the instance variable name (including the @ sigil) as a symbol to the value. Class variables, marked with the @@ sigil are also looked up in a hash associated with the class object. The difference is that for class variables, if the key is not found in the hash, the search considers iteratively up the superclass chain, and for class methods, it's the class and not the metaclass chain which is traversed. This means that class variables are visible to both instance and class methods of the class where they live and that classes subclasses. The MRI, at least the last time I looked, actually puts class variables in the same hash as class instance variables, i.e. the class objects instance variable hash. It's the difference in the sigils which affects how they are seen and used. -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/