• 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
problem with subclassing a cluster class
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

problem with subclassing a cluster class


  • Subject: problem with subclassing a cluster class
  • From: Ivan Kourtev <email@hidden>
  • Date: Sun, 5 Mar 2006 15:18:30 -0500

Hi,

I want to subclass NSDictionary so that I can override - (NSScriptObjectSpecifier *)objectSpecifier to make my app scriptable. I understand that NSDictionary is a class cluster so I follow the prescriptions in Apple's document "Cocoa Objects", the chapter on class clusters. I am trying to use the "Composite Object" pattern (to be honest, I didn't fully understand the difference between this and the "True Subclass" pattern because they are both derived from the cluster so seem like subclasses).

At any rate, my problems seem to arise from the fact that I want to initialize an instance of my subclass with the variadic function + (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...

From everything I have read and tried, it appears that I cannot simply pass the arg list of a variadic function to another variadic function within it. So I went for something like the code attached at end -- compiles with no warnings but I get an *** Uncaught exception: <NSInternalInconsistencyException> *** -[NSCFDictionary setObject:forKey:]: mutating method sent to immutable object at runtime.

So I try changing NSDictionary to NSMutableDictionary and things only start working somewhat when I also derive MyDictionary from NSMutableDictionary. But now I get runtime errors like *** Uncaught exception: <NSInvalidArgumentException> *** -count only defined for abstract class. Define -[MyDictionary count]! and I keep fixing them but a new one keeps popping in (count, keyEnumerator, etc.)

Is the overriding of all these methods something I really should do or am I missing something here? In rereading the Apple doc referenced above "Since the cluster’s abstract superclass is the only publicly visible node in the cluster’s hierarchy, the first point is obvious. This implies that the new subclass will inherit the cluster’s interface but no instance variables, since the abstract superclass declares none. Thus the second point: The subclass must declare any instance variables it needs. Finally, the subclass must override any method it inherits that directly accesses an object’s instance variables. Such methods are called primitive methods." so may be I should really redefine all primitive classes?

But then, two other points in question:

1. How does one tell which methods of a class cluster are primitive and which aren't?
2. Assuming I pulled it off, my non-mutable dictionary class is still based on NSMutableDictionary which just doesn't seem right? This feels like a contradiction to me -- there has to be a more elegant solution here that I can't see. Help anyone?


Cheers,

-- ivan



#import <Foundation/Foundation.h>

@interface MyDictionary : NSDictionary { NSDictionary *embeddedDictionary; }
- (id)init;
+ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...;
@end


@implementation MyDictionary

- (id)init
{
    self = [super init];
    if ( self ) {
        embeddedDictionary = [[NSDictionary alloc] init];
    }
    return self;
}

+ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...
{
// argument list empty: not much to do but return an empty dictionary
if ( firstObject == nil ) {
return [[[self alloc] init] autorelease];
}


// arguments exist: create dictionary and insert keys and objects from list
id dictionary = [[self alloc] init];
va_list argList;
id anObject, aKey;
va_start( argList, firstObject );
aKey = va_arg(argList, id);
NSLog( @"The first object from the argument list is %@", firstObject );
NSLog( @"The next object from the argument list is %@", aKey );
if ( aKey == nil ) {
NSLog( @"Invalid arg list to %s", __PRETTY_FUNCTION__ );
assert( NO );
} else {
NSLog( @" Now inserting %@ for key %@", firstObject, aKey );
[dictionary setObject:firstObject forKey:aKey];
}
while ( ( anObject = va_arg( argList, id) ) != nil ) {
aKey = va_arg( argList, id);
if ( aKey == nil ) {
NSLog( @"Invalid arg list to %s", __PRETTY_FUNCTION__ );
assert( NO );
} else {
NSLog( @" Now inserting %@ for key %@", anObject, aKey );
[dictionary setObject:anObject forKey:aKey];
}
}
va_end( argList );
return [dictionary autorelease];
}
@end


int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *obj = [NSString stringWithString:@"myObject"];
NSString *key = [NSString stringWithString:@"myKey"];
MyDictionary *dict = [MyDictionary dictionaryWithObjectsAndKeys:obj, key, nil];
NSLog( @"Created dictionary: %@", dict );
[pool release];
return 0;
}


_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: problem with subclassing a cluster class
      • From: Greg Herlihy <email@hidden>
  • Prev by Date: Re: GDB: without symbol name?
  • Next by Date: NSFontPanel Unreliable
  • Previous by thread: Re: Text Layout problems
  • Next by thread: Re: problem with subclassing a cluster class
  • Index(es):
    • Date
    • Thread