0

In Java, a factory constructor can be defined in an abstract superclass like:

public static Parent createChildFromType(int type) {
    switch (type) {
        case 0:
            return new Child1();
        case 1:
            return new Child2();
        default:
            throw new Exception();
    }
}

But, in Objective-C, I'm getting a 'No known class method for selector "alloc"' for case 1:

#import "Child1.h"
#import "Child2.h"

@implementation Parent

+(id)createChildFromType:(int)type {
    switch (type) {
        case 0:
            return [[Child1 alloc]init];
        case 1:
            return [[Child2 alloc]init];
        default:
            @throw [NSException exceptionWithName:NSInternalInconsistencyException 
                    reason:@"Invalid subclass type." 
                    userInfo:nil];
     }
}

-(void)someAbstractMethod {
    @throw [NSException exceptionWithName:NSInternalInconsistencyException 
                    reason:[NSString stringWithFormat:@"You must override %@ in a subclass.", 
                            NSStringFromSelector(_cmd)] 
                    userInfo:nil];
}

@end

Both Child1.h and Child2.h have #import "Parent.h" because I'd like to make a call to someAbstractMethod, without knowing beforehand, which subclass I'm calling it on:

-(void)someVoodooMethod:(int) type {
    Parent *child = [Parent createChildFromType: type];
    [child someAbstractMethod];
}

I have a hunch that it's because of the redundant #import "Parent.h" in the @implementation Parent, but I haven't thought of a way around it. Any suggestions?

EDIT:

I suppose the code for Child1.h should be included:

#import "Parent.h"
@interface Child1 : Parent
@end

And Child2.h

#import "Parent.h"
@interface Child2 : Parent
@end
iamreptar
  • 1,461
  • 16
  • 29

1 Answers1

0

You need to forward declare parent in the childs.

Here's a link explaining forward declaration in obj-c: Objective-C: Forward Class Declaration

Just add

@class Parent; 

In the child1.h , child2.h.

In child1.m , child2.m you can include Parent.h

Community
  • 1
  • 1
MichaelCMS
  • 4,703
  • 2
  • 23
  • 29
  • `@class` assures the linker that there's a class with that name, allowing the interface to subclass it without knowing it's details. How does the implementation resolve/expand the `#import`? – iamreptar Aug 01 '14 at 09:25
  • You remove the #import "Parent.h" from child1.h and child2.h and you forward declare parent . This is needed only if you use "Parent" in your child1.h and child2.h . If you don't use it, you can just remove it from the header files and add it to the .m files. It will work fine, and you won't run into the problem you are having. – MichaelCMS Aug 01 '14 at 09:33
  • In objective C (and C, C++) objects are created from the .m files. Header files are used only to describe methods / classes in order to be used outside the .m of the object. In java you have both header and .m file in your .java file. At a first step the compiler will check if every name you use is previously declared (here the .h files are used). Then it starts compiling each object individually with references to other object names (here the .m are needed). Then it links objects between one another (here the generated .o or .obj are used). – MichaelCMS Aug 01 '14 at 09:40
  • I've updated the question for clarity. Child1 and Child2 are subclasses of Parent. Thus, both subclasses depend on the super. Applying your suggestions gives the semantic issue, `Attempting to use the forward class 'Parent' as a superclass of 'Child1'`. – iamreptar Aug 01 '14 at 10:52