• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Categories and adding instance variables
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Categories and adding instance variables


  • Subject: Re: Categories and adding instance variables
  • From: "Dennis C. De Mars" <email@hidden>
  • Date: Sun, 1 Aug 2004 12:59:07 -0700

On Aug 1, 2004, at 10:27 AM, Kay Roepke wrote:

Yes, I know it doesn't work. I know about subclassing.

Now that I said that ;-), here's my question:

Is there a technical reason that you cannot add instance variables to class using categories?
Or is it just convenient for the runtime?

The experts can address this more thoroughly, but I believe it is because there may be code that did not see the category, possibly compiled before you defined the category, and that code will allocate memory for the instance variables without allocating space for your new instance variable. Initialization is an issue also.

It is possible, in principle, for an OO language to allow instance variables to be added at runtime. Dylan can do this, possibly some of the OO flavors of Lisp (I don't know about Smalltalk). But you potentially lose some efficiency in accessing the instance variables in order to allow this possibility, and although Objective C is pretty dynamic, it does make some concessions to retain the core efficiency of C.

I have this generated class, lets call it Lexer. It inherits from Scanner, which is part of an existing framework.
While generating Lexer's source code, I also end up with a enum containing the tokens to be produced by Lexer.

Of course I could simply add this enum to the Lexer class and be done with it, but guess what:
I have a Parser class which wants the very same enum, in order to know which tokens it must
handle. Obviously, I don't want that enum to be duplicated in my (albeit generated) code for
hygenical reasons.
In the C++ version this is done via multiple inheritance and in Java one could simply make an
interface for this. ObjC on the other hand craps out.

I can't quite figure out from this description what the problem is. Does Parser also derive from scanner, so you want to put this enum in Scanner so both Lexer and Parser will share it?

Also, if you think you can solve this in Java with an interface, why can't the same solution be applied in Obj C with a protocol? Obj C protocols are basically the same thing as Java interfaces, aren't they? You can't declare instance variables in interfaces, so I'm not quite sure how you would solve the problem in Java.

Does anyone have a suggestion how this could be cleanly done?
One thing I came up with would be to use a static dictionary and get the tokens from there, but that
seems like overkill to me.

The static dictionary is pretty much the standard thing to do when you want to add "instance variables" to a category. You create a private static dictionary associated with that class, and arrange to have each instance enter itself as a key of the dictionary, with the value being the instance variable (or variables) you want to add. It is clearly less efficient than having a real instance variable and takes some effort to set up. so it is a matter of how badly you need the instance variable.

Personally, I would just add the enum to each subclass. (I've become more cavalier about issues of type safety and type identity since I've been using Objective C). If you want to put a more formal veneer over this, you could do the following:

1) Add a category to the Scanner class that contains setter and getter methods for the enum. Implement these in the category by having them print an error message or raise an exception or something (i.e. it is not legal to use the methods directly, they must be overridden).

2) Add the enum instance variables to the subclasses and override the accessor methods to use the variable.

3) Only use the accessor methods to access the variable.

This allows you, for instance, to access the enum on Scanner* pointers without knowing whether they are Lexer or Parser (and without the compiler complaining).

A variation would be to define a protocol instead of category with these accessor methods, and then have Lexer and Parser inherit from this protocol as well as Scanner. Again, you'd have to implement the methods separately in each class. Then you could refer to objects of either type with pointer of type id<TokenProtocolName> (or whatever you decide to call the protocol). This may be similar to the solution you were thinking of in Java.

- Dennis D.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.


  • Follow-Ups:
    • Re: Categories and adding instance variables
      • From: Kay Roepke <email@hidden>
References: 
 >Categories and adding instance variables (From: Kay Roepke <email@hidden>)

  • Prev by Date: Custom Composite Operators?
  • Next by Date: Re: Bindings: Custom Controller Keys ...
  • Previous by thread: Categories and adding instance variables
  • Next by thread: Re: Categories and adding instance variables
  • Index(es):
    • Date
    • Thread