views:

137

answers:

3

I have a small class hierarchy where I would like to have a child class be a property of it's parent class and all related subclasses. Essentially,

  • I have AbstractClass with a property of GroupClass.
  • GroupClass is a child of AbstractClass.
  • UsableObjectClass is a child of AbstractClass and uses GroupClass.

If I do the following...

#import <Cocoa/Cocoa.h>
#import "GroupingClass.h" // I've bounced this between @class as well.
@interface myAbstractClass : NSObject {
    GroupingClass* parentGroup;
}
@property (readwrite, assign) GroupingClass* parentGroup;
@end

#import "myAbstractClass.h" // ERROR LOCATION
@implementation myAbstractClass
@synthesize parentGroup;
@end

#import <Cocoa/Cocoa.h>
@interface GroupingClass : myAbstractClass {
}
@end

#import <Cocoa/Cocoa.h>  // ERROR LOCATION IN ALL CHILD CLASSES OF AbstractClass
@interface GroupingClass : myAbstractClass {
}
@end

...I get this funky "Line Location GroupingClass.h:3: error: cannot find interface declaration for 'myAbstractClass', superclass of 'GroupingClass'" at the noted error locations.

I've tried various ways of getting this to work (yes, I know the above is totally wrong), Categories and Protocols seems the be right direction but this is becoming only so much flailing around now, and I really just need a shove in the right direction. I think I'm missing something grossly fundamental (frankly, I'm a little embarrassed to be asking this question).

I'm currently porting this application from REALbasic and something like this was a breeze; I could just add the property as the child class and it just worked. Objective-C...not so much.

Any help, even just a hint, is greatly appreciated!

A: 

You have what is called a circular reference or dependency. Your base class is dependent upon its child class, which is in turn dependent upon the base class.

I suggest you heavily reconsider your class structure.

Randolpho
Right, but there still has to be a way to manage this. UsableObjectClass at least needs to know when it has been applied to a GroupingClass. A wrapper class for GroupingClass was one idea I threw around.
Philip Regan
The question "why" comes to mind. *Why* does UsableObjectClass need a reference to GroupingClass, and *why* is that reference encoded in the abstract base class? If I knew more about your problem I might be able to suggest a different structure, but the one you have appears to follow an antipattern.
Randolpho
Essentially, GroupingClass is used to enhance object selection in a custom interface. The group property is tested when an object is selected. If an object has been grouped, then that group is used as a jumping off point to find the topmost parent group so that all of the related objects are selected. I suppose I should have mentioned that upfront.
Philip Regan
Actually, it's not a true circular dependency. It's more of a loopback like you would typically see in a struct for creating linked list nodes. However, I agree that the structure is extremely confusing. Hopefully, using an @class forward declaration will put the author of the question back on the right track to sane design. :-)
Quinn Taylor
+1  A: 

You should be able to use a @class declaration in your header and import the subclass's header in your implementation file.

Chuck
That was the bit I was missing. Thanks!
Philip Regan
+2  A: 

What you're looking for is a "forward class declaration". At the top of the AbstractClass header, add

@class GroupingClass;

This tells the (unfortunately slightly archaic) C compiler that there will be a class called GroupingClass and that it can allocate space for variables of that type appropriately.

Barry Wark