From: Rick DeNatale Date: 2009-11-28T23:46:26+09:00 Subject: Re: Class variables, instance variables, singleton; Ruby v. C++ On Sat, Nov 28, 2009 at 8:00 AM, Ralph Shnelvar wrote: > DAB> And of course this is one of the (many) problems with class variables: > DAB> they make obscure the otherwise rather simple notion that classes can > DAB> have instance variables because classes are objects and any object can > DAB> have instance variables. > > David ... this may be the higher-level gestalt that I was missing.  It > sure sounds like it. > > Let me flesh out my questions/comments about this paragraph so that you and > others have something specific to answer.  Let's call the classed  F & > G. > > (1) OK, classes are (i) objects; (ii) are executable code. I wouldn't say that classes are executable code. However the difference between Ruby and C++ here is that in C++ a class is really just a C Struct definition with new features like virtual member functions and inheritance. It's a static compile time construct. In Ruby on the other hand, classes are defined at run time as code is executed, and the stuff inside a class definition is executable code. Another related difference is that in C++ the class describes which instance variables are present in every instance of that class by virtue of the instance variables (members) being statically declared. In Ruby an object gets instance variables one by one only when it executes a method which sets the instance variable. Since classes are objects this applies to classes as well. A primary purpose of a class is to collect method implementations which will be part of the repertoire of instances of that class. So for example class A # At this point the class has no class instance variables @class_instance_variable1 = 42 # This statement is executed when the class def is, so # after this A has a class instance variable # The following defines a method which will be in the repertoire of instances of A or any # of its subclasses def some_method @instance_var = "Hello" end # The self. makes the following a method of the class A. We call this a class method # it will also be in the repertoire of any class objects which subclass A (but not their instances) def self.a_class_method @class_instance_variable2 = [1, 2, 3] end end a = A.new # At this point of execution: # # The class A has ONE class instance variable @class_instance_variable1 # # a, which is an instance of A, has NO instance variables a.some_method # And now a has an instance variable named @instance_var A.a_class_method # And now A has another class instance variable @class_instance_variable2 > (2) If I do the following >      class F >      end >      f = F.new >      F.class  # class >      f.class  # F > this makes sense to me. > > What (relevant and important conceptually) messages (other than "new") > can I send to a class?  But see (3), below. Well like any object the answer to that depends on the class. All classes are instances of Class, which defines three methods, only two of which are normally called by user code. Class#allocate which actually allocates the storage for a new instance, this is rarely if ever overriden or called directly Class#new which calls allocate to get a new instance and then calls intialialize on the new instance passing any arguments along. This is called often but rarely overridden. Class#superclass which returns the superclass of the class, again called but almost never overridden. In addition Class is a subclass of Module, and inherits from module the ability to collect methods and to serve as a nested namespace. So every class object has the instance methods defined in Module as part of its repertoire, I'll leave you to look these up. And of course the instance methods defined in Object and the module Kernel (which is included by Object) are part of the repertoire of very Object and therefore every object which happens to be a class. Some Ruby standard library classes like Array, Dir, File and others define additional class methods specific to the class and its subclasses. > (3) >    class F >      def sub1 >        @@x = 1 >      end >    end > >    class G >      self.sub1 >        @@x=2 >      end >    end > >    # Why?  Didn't the interpreter "see" @@x in class F? >    F.class_variables  # [] See my explanation above. In this regard class variables like instance variables F doesn't have any class variables because the sub1 method hasn't been executed. G does because you execute sub1 inside its class definition code. I assume that you actually defined G as a subclass of F or you would have gotten an undefined sub1 method error. And you have invalid syntax in that snippet because there's an extra end class G self.sub1 @@x = 2 end # this ends the class def which consists of two end >    # makes sense >    G.class_variables  # ["@@x"] > >    f = F.new > >    # Why?  Shouldn't the method inherit from the class? >    f.class_variables  # undefined method Because f is an instance of F, and is not a class, class_variables is a method defined in Module, not Object or kernel > >    f.sub1  # 1 > >    # makes sense.  class variable now explicitly executed >    F.class_variables # ["@@x"] > >    # How to use class_variable_get if the method is private??? >    F.class_variable_get(:@@x)  # error private method! F.send(:class_variable_get, :@@x) As others have pointed out class variables are a pretty wonky area of Ruby. In Ruby 1.8 if G is a actually a subclass of F, then whether or not @@x is the same instance variable for both depends in some cases on whether or not F got its instance variable before G did or not. When a class variable is initialized Ruby 1.8 looks through the chain of superclasses to see if a class variable with that name already exists, and if so uses that definition. If not it defines it for the current class. Ruby 1.9 changed that so that now class variables are no longer shared with subclasses. Now it may seem hard or harsh, but I'd recommend that you try to forget what you know about C++ when learning Ruby. Although C++ and Ruby are both said to be object-oriented, they come from two very different views of what that means. C++ is the epitome of what Ralph Johnson calls the "Software Engineering" school, where objects are seen as an extension of abstract data types. Ruby is of what he calls the "Mystical" school where objects are seen as entities which encapsulate both the data representation and the methods which operate on the data, and which interact with other objects only by message invocation of methods, looked up by name at runtime. Java is influenced by the SE school, but is more dynamic in other regards. Other mystical languages include Smalltalk, Self, and JavaScript although JavaScript is not fundamentally OO. -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Twitter: http://twitter.com/RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale