lerman@stpstn.UUCP (Ken Lerman) (10/03/90)
As a long term user and developer of Objective-C, I've often heard people comment that it would be nice if Objective-C had "Class Variables." On several occasions, I've had use for them, myself. The problem addressed by this article, is: What are class variables? Here are some possible answers: Class variables are like instance variables, except that all instances of the class share a common variable. Each class may declare some class variables and has these plus those of its superclass. Some alternatives are: 1 -- each subclass has its own copy of its parent's class variables 2 -- all subclasses share a single copy of their parent's class variables The questions for the net are: 1 -- Would you like to see class variables added to Objective-C? 2 -- Which of the two types of class variables discussed above would you like to see? (Or some other version). 3 -- Do you have some examples of how you would use class variables? Send me email or answer to the net. I will summarize if and when appropriate. Disclaimer: I speak for only myself in this article. Ken
rmyers@ics.uci.edu (Richard E. Myers) (10/04/90)
Though I'm just a novice in Objective-C I have run across a case where class variables would simplify things. In answer to your first two questions, I believe class variables would be useful and that case one would be the better system. >** 1 -- each subclass has its own copy of its parent's class variables > > 2 -- all subclasses share a single copy of their parent's class variables I think at run time each subclass should be thought of as distinct from its parent and thus have it's own variables. A programmer shouldn't have to worry about changes made to the class variables of a parent class or sibling class effecting its own class variables. Unless someone can give examples why this ability would be needed then to minimize side effects system one seems adequate. A hypothetical use that makes me favor class variables is as follows: Suppose the first instantiation of a class "PriorityQ" puts its id into a class variable call "defaultQ". Subsequent calls to the class "PriorityQ" using the method "+newORdefault" would then return the id contained in "defaultQ" or a new id if the "defaultQ" variable is nil. If (using another method) the variable "defaultQ" was changed then any new invocations of the "+newORdefault" method would return the new id in the class variable "defaultQ". What bothers me about this example is that (I think) NeXT has produced a similar effect in their "Conductor" class (which can be found within the MusicKit). If class variables don't exist in Objective C then I'm not sure how they did this. I hope I haven't over looked something due to my limited experience with Objective C. Cheers, -- Richard ------------------------------------------------------------------------------- "Programs were devised whose `thinking' was to human thinking as a slinky flipping end over end down a staircase is to human locomotion." -- D.R. Hoffstadter ------------------------------------------------------------------------------- Richard Myers / 6 Exeter / Irvine, CA 92715 / 714-854-4410 / rmyers@ics.uci.edu -- ------------------------------------------------------------------------------- "Programs were devised whose `thinking' was to human thinking as a slinky flipping end over end down a staircase is to human locomotion." -- D.R. Hoffstadter
dandb@k.gp.cs.cmu.edu (Dean Rubine) (10/04/90)
For the simple cases, class variables can be simulated in Objective-C with static variables declared in the same file that the class is declared. This is limited in that superclasses or subclasses of the class cannot access the class variables directly, but instead need to call methods in defining class. Actually, from a modularity standpoint, that's probably not too bad, but it goes against the Objective C philosophy, such as it is. For more complicated needs, I think the suggestion that each subclass have its own copy of its parent's class variables is the correct one, since it's easy to do the other case (every subclass accessing the same, single copy of their parent's class variables) with statics or globals. I came across the need for class variables when I needed to associate an event-handler object with every subclass of a given class - with the correct semantics, a single class variable, in the parent class, would do the job. I solved the problem in the obvious way, with an association list, where I associated the factory object with the event-handler object. Actually, I implemented the general case of property lists, which associate name/property pairs with arbitrary objects. Then the property lists' name/property/value implement class variables as class-object/class-var-name/class-var-value. [Alternatively, property lists names can be the variable names and properties can be class objects; it depends on the implementation as to which is better.] As far as I know, there are no conceptual reasons why class variables haven't been implemented in Objective-C yet; it just seems that no one has gotten around to it. In point of fact, there are already a fixed number of class variables already stored per class (I'm refering to the fact that each factory object has an "isa" class variable, a "clsSuper" class variable which points at the factory object of the superclass, a "clsName" which is a string, "clsTypes" which describes the type instance variables of the class, as well as size information of instances, and a dispatch table, both of which can be considered class variables as well). All that's needed is some syntax for adding to this existing structure of class variables on a per class basis. -- ARPA: Dean.Rubine@CS.CMU.EDU PHONE: 412-268-2613 [ Free if you call from work ] US MAIL: Computer Science Dept / Carnegie Mellon U / Pittsburgh PA 15213 DISCLAIMER: My employer wishes I would stop posting and do some work.
kenneth@EB.se (Kenneth Persson) (10/08/90)
I first replied to the author of the original article, but this is the place for discussion: rmyers@ics.uci.edu (Richard E. Myers) writes: >In answer to your first two questions, I believe class variables would >be useful and that case one would be the better system. >>** 1 -- each subclass has its own copy of its parent's class variables >> >> 2 -- all subclasses share a single copy of their parent's class variables I would prefer case 2! > I think at run time each subclass should be thought of as distinct >from its parent and thus have it's own variables... Inheritance is just an implementation technique to minimize redundant code. At run time there is no subclasses or superclasses, just objects (and classes that I think of as objects too). If you have class hierarchy (bad example): Picture | \ TextPic GeometricPic you want them to share the same Printer. etc etc. Note that you can simulate class variables with the static mechanism. Since every class is declared in it's own file a static works like a class variable, with the restriction that it's not inherited. If you supply the class with a factory method that return the static you can use it in subclasses too. |+cPrinter| and |+cPrinter: aPrinter|. -- +-------------------------+--------------------------+ | Kenneth Persson | email: kenneth@eb.se | | EB Signal AB, Sweden | voice: +46 8 726 2267 | +-------------------------+--------------------------+
gregor@parc.xerox.com (Gregor Kiczales) (10/15/90)
With regard to the question about what kind of class variables people want, here is a comment from another community. > 1 -- each subclass has its own copy of its parent's class variables > > 2 -- all subclasses share a single copy of their parent's class variables In CLOS, we did 2. It seemed natural, and it works well. But, there are plenty of cases where what users want is 1. Fortunately, in CLOS, the Metaobject Protocol makes it easy for users to add this kind of class variable themeselves. But, given that you don't have a Metaobject Protocol, I would say do both 1 and 2.
moose@svc.portal.com (10/16/90)
In article <GREGOR.90Oct14231438@spade.parc.xerox.com> gregor@parc.xerox.com (Gregor Kiczales) writes: > >With regard to the question about what kind of class variables people >want, here is a comment from another community. > >> 1 -- each subclass has its own copy of its parent's class variables >> >> 2 -- all subclasses share a single copy of their parent's class variables I think this arguement is beginning to get silly. If you do #2, you can always do #1 by adding a new variable and overridding all methods that affect the variable in question. If you do #1, there is no way to do #2. Therefore, #2 should be done. -- Michael Rutman | moose@svc.portal.com Cubist | makes me a NeXT programmer Software Ventures | That's in Berkeley smile, you're on standard disclaimer | <fill in with cute saying>
dandb@k.gp.cs.cmu.edu (Dean Rubine) (10/17/90)
The choices: #1 -- each subclass has its own copy of its parent's class variables #2 -- all subclasses share a single copy of their parent's class variables In article <1990Oct15.185718.8342@svc.portal.com> moose@svc.portal.com writes: >I think this arguement is beginning to get silly. If you do #2, you can >always do #1 by adding a new variable and overridding all methods that affect >the variable in question. If you do #1, there is no way to do #2. >Therefore, #2 should be done. >Michael Rutman Hmmm. I too thought the argument was silly, but I reached the opposite conclusion. I thought: #2 can be perfectly simulated with global (or static) variables, while #1 gives some new functionality. I already gave an example in a previous post: #2 allows an event handler to be associated with each subclass of View, just by declaring a class variable "eventHandler" in the View class (and presumably defining some factory methods in View which reference "eventHandler"). As I read Mr. Rutman's reasoning, given choice #2, all I'd have to do to associate an event handler with every subclass of View is declare a variable (class or static) in EVERY subclass, and provide appropriate methods in EVERY subclass. Yeech. Note that I'd likely be repeating the same code in every subclass - this seems contrary to the object-oriented paradigm, in which inheritance is supposed to be used to avoid such of repetition of code. This problem doesn't come up with class variables of kind #1. -- ARPA: Dean.Rubine@CS.CMU.EDU PHONE: 412-268-2613 [ Free if you call from work ] US MAIL: Computer Science Dept / Carnegie Mellon U / Pittsburgh PA 15213 DISCLAIMER: My employer wishes I would stop posting and do some work.
mst@vexpert.dbai.tuwien.ac.at (Markus Stumptner) (10/17/90)
From article <1990Oct15.185718.8342@svc.portal.com>, by moose@svc.portal.com: > In article <GREGOR.90Oct14231438@spade.parc.xerox.com> gregor@parc.xerox.com (Gregor Kiczales) writes: >>With regard to the question about what kind of class variables people >>want, here is a comment from another community. >> >>> 1 -- each subclass has its own copy of its parent's class variables >>> >>> 2 -- all subclasses share a single copy of their parent's class variables > > I think this arguement is beginning to get silly. If you do #2, you can > always do #1 by adding a new variable and overridding all methods that affect > the variable in question. Come on - "you can always do it by <some complex operation>" has no weight whatsoever as an argument. On that basis, I have seen people argue that all the constructs you need for object-oriented programming are the multiple subroutine entry points provided by FORTRAN II. The need for using different values for a global variable in subclasses is something that occurs rather often. Example: If I want to present ships on a screen, I want a specific picture (call it "icon", if you will) for each class of ship (tankers, freighters, etc.) The most natural way is certainly to treat class variables the way one treats methods: If I want to override it, I do, if not I use the inherited value. [If you like, you can then consider methods as class variables containing function objects.] I do not see why an approach that works perfectly well with methods should not also apply to class variables. Both #1 and #2 can easily be united in this way. Unfortunately, that distinction is present in Smalltalk-80 and some other languages (perhaps for efficiency reasons? I don't know) and some people seem to want to perpetuate it. > If you do #2, you can > always do #1 by adding a new variable and overridding all methods that affect > the variable in question. Which means either that (1) I may access class variables in my programs only by way of by a specific method. Then I only have to change the method's code in a subclass to get a new value. In effect, I have then lost most of the meaning of what is called a 'class variable'. Besides, I can always get the original value by using the variable directly. This is rather error-prone and somehow contradicts the idea of 'overriding.' or that (2) every time I want a different value in a subclass, I have to override (i.e., copy textually without changing the code) ALL methods using that variable. This may blow up the code (source and binary) size of the system enormously and (a) is a good way to make the relationship between super- and subclass quite confusing to somebody who wants to understand the code - after all, there might just be some difference in all those lots of methods which outwardly look the same, and (b) when you change some methods (possibly in a way totally unrelated to the variable that started the mess), you have to change all the textually identical copies of these methods that exist in subclasses. Read Stroustrup's paper from the first ECOOP conference to find out about the difference between "supporting" and "allowing" features. > If you do #1, there is no way to do #2. > Therefore, #2 should be done. It's easy to do #1 in a way that allows #2; #2 alone is a pain in many situations. Therefore, #1 is better. Markus Stumptner mst@vexpert.dbai.tuwien.ac.at Technical University of Vienna vexpert!mst@uunet.uu.net Paniglg. 16, A-1040 Vienna, Austria ...mcsun!vexpert!mst
boissier@irisa.fr (franck boissiere) (10/17/90)
From article <1990Oct15.185718.8342@svc.portal.com>, by moose@svc.portal.com: > In article <GREGOR.90Oct14231438@spade.parc.xerox.com> gregor@parc.xerox.com (Gregor Kiczales) writes: >> >>> 1 -- each subclass has its own copy of its parent's class variables >>> 2 -- all subclasses share a single copy of their parent's class variables > > I think this arguement is beginning to get silly. If you do #2, you can > always do #1 by adding a new variable and overridding all methods that affect > the variable in question. If you do #1, there is no way to do #2. > Therefore, #2 should be done. > -- I think there should be a clear distinction between 1 and 2. Just take a look at what they can be used for: With case 2 all instances and "subinstances" (instances of subsequent subclasses) will be able to share a common variable which can be a common setting or a default value for some attribute (default size for example). This advocates for the so called class variables, accessible from the class and instances methods. With case 1 you can store values which can be shared throughout the class scope but are not relevant to subclasses. One example: suppose you have a class named cursor which is a subclass of a Bitmap class with a new attribute for the "hot spot". You may think of defining the default bitmap as a 16x16 White bitmap, name it default, and be able to have with the same name a default cursor which can be something else, but more important, as a cursor it NEEDS a hot spot. Another case which I use quite often is to have a hierarchy of object which can be displayed graphical with "standard" representation yet specific to each of the object classes. You can do it efficiently with case 1 defining a glyph class variable, and initialize it differently for each class in the subhierarchy. This is what can be called class instance variables, a common name but with a different specificity at each level of the hierarchy. Of course if you don't have 1 and 2 you can always redesign the implementation and tweak it to be able to solve my examples, but there will always be some cases not solved. As a summary 2 is clearly needed, 1 might be very usefull and powerful even if it is difficult do understand its power at a first glance. A good environment should provide 2, to be outstanding you need 1. -- Franck BOISSIERE boissier@irisa.irisa.fr Prototyping Lab Manager boissier@ccettix.UUCP C.C.E.T.T. B.P. 59 boissier%irisa.irisa.fr@uunet.uu.net 35512 CESSON SEVIGNE CEDEX FRANCE
moose@svc.portal.com (10/18/90)
In article <10777@pt.cs.cmu.edu> dandb@k.gp.cs.cmu.edu (Dean Rubine) writes: [let's leave these choices up for all future posts] The choices: #1 -- each subclass has its own copy of its parent's class variables #2 -- all subclasses share a single copy of their parent's class variables > > As I read Mr. Rutman's reasoning, given choice #2, all I'd have to do to >associate an event handler with every subclass of View is declare a variable >(class or static) in EVERY subclass, and provide appropriate methods in EVERY >subclass. Yeech. Note that I'd likely be repeating the same code in every >subclass - this seems contrary to the object-oriented paradigm, in which >inheritance is supposed to be used to avoid such of repetition of code. This >problem doesn't come up with class variables of kind #1. A bit of code is going to follow. int myGlobal; + saveMyGlobal:(int)number { myGlobal = number; return self; } + (int)getMyGlobal { return myGlobal; } now, all references to myGlobal are through these lovely factory methods. (Instance methods would work fine, but who cares :->) Subclass now. We want to override myGlobal with int myOwnGlobal; We override saveMyGlobal and getMyGlobal with + saveMyGlobal:(int)number { myOwnGlobal = number; return self; } + (int)getMyGlobal {return myOwnGlobal;} We could even go so far as to have something like + saveMyGlobal:(int)number { myGlobal -= myOwnGlobal; //to remove the old value myGlobal += number; //keep a total for all subclasses myOwnGlobal = number; return self; } Now, show me how to do that in #1, a case where I actually want the subclass to have its own copy of the variable and a copy of the superclasses variable. -- Michael Rutman | moose@svc.portal.com Cubist | makes me a NeXT programmer Software Ventures | That's in Berkeley smile, you're on standard disclaimer | <fill in with cute saying>
craig@Neon.Stanford.EDU (Craig D. Chambers) (10/18/90)
In article <3713@vexpert.dbai.tuwien.ac.at> mst@vexpert.dbai.tuwien.ac.at (Markus Stumptner) writes: >The most natural way is certainly to treat class variables the way one >treats methods: If I want to override it, I do, if not I use the >inherited value. [If you like, you can then consider methods as class >variables containing function objects.] I do not see why an approach >that works perfectly well with methods should not also apply to class >variables. Both #1 and #2 can easily be united in this way. >Unfortunately, that distinction is present in Smalltalk-80 and some >other languages (perhaps for efficiency reasons? I don't know) and >some people seem to want to perpetuate it. Take a look at the Self language, originally designed by David Ungar and Randy Smith [OOPSLA '87]. It does treat variables just like methods, and you can override a variable with another variable or even with a method (and of course you can override a method with a variable), and so would solve the class variable controversy exactly as you describe. Of course, treating a variable like a method has an adverse effect on performance in simple compilers, and that's probably one reason why most languages are not as flexible as Self in this regard (Trellis/Owl is one notable exception, at least for instance variables; there's no inheritance at the class level in Trellis/Owl). But more sophisticated compilers can eliminate this overhead, at least for accessing instance and class variables of "self", by compiling a distinct version of a method for each inheriting subclass. See the papers on the Self compiler for more details [e.g. OOPSLA '89, SIGPLAN '90]. -- Craig Chambers P.S. Self doesn't have classes, instead using simple object inheritance to model both class inheritance and instantiation. But languages with classes can still learn from the features pioneered in classless languages, and adopt the good ones (like treating variables as methods).
daniels@ogicse.ogi.edu (Scott David Daniels) (10/18/90)
In article <1990Oct17.132314.26739@irisa.fr> boissier@irisa.fr (franck boissiere) writes: >From article <1990Oct15.185718.8342@svc.portal.com>, by moose@svc.portal.com: >> In article <GREGOR.90Oct14231438@spade.parc.xerox.com> gregor@parc.xerox.com (Gregor Kiczales) writes: >>> >>>> 1 -- each subclass has its own copy of its parent's class variables >>>> 2 -- all subclasses share a single copy of their parent's class variables [paraphrased] ...case 2 all instances of the class or its subclasses share 1 variable ...case 1 of each distinct class or subclass share variables My Suggestion: Provide a way to share an initial value for the unshared variables. If you want case 2, make the initial value a reference to the single shared storage. If references don't work nicely, how about an Object ID? I have (in a system with only type 1 class variables) used class variables to keep such things as instance counts and rings of instances of a class. These things were mplemented in OBJECT, and inheritance propogated them throughout the tree. Even more important were some of the short-term hacks I put in for debugging which propogated counts of allocations and deallocations and allowed me to chase memory leaks. With my system (the type 1 variables), I added in accounting code at allocate and delete times, and could, at a function invokation, display lists of classes and counts where the number of living instances had changed between calls. Such code is, admittedly, ``tricky'' code, but in an evening I had written it and used it to chase memory leaks, and then removed it from the system the following day (so the system kept its old memory efficiency). I was language maintennance/implementor here, but I really suspect that it is more common to want distinct variables per class. -Scott Daniels daniels@cse.ogi.edu