[comp.lang.objective-c] Requirements for Class Variables for Objective-C

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