views:

91

answers:

4

I am porting a project from C# to Objective-C, and I would like to know how to implement an Internal class in Objective-C (Internal meaning only visible inside of this project).

For example, I have the code in C#:

public abstract class AbstractBaseClass : AInterface
{
     // methods go here
}

internal class InternalSubclass : AbstractBaseClass
{
     // methods go here
}

This Is the code I have converted so far:

// AbstractBaseClass.h
#import <Foundation/Foundation.h>
#import "AInterface.h"

@interface AbstractBaseClass : NSObject<AInterface>

// methods go here

@end

// AbstractBaseClass.m
#import "AbstractBaseClass.h"

@implementation AbstractBaseClass

-(void) abstractMethod
{
      [NSException raise:@"abstract method" format:@"This method is abstract, and thus cannot be called"];
}

// more methods

@end

Where should I put the interfaces and implementations of InternalSubclasses? Should they be in a separate file called InternalClasses.h/m? Or should I just not have a header for those files and just have a .m file for them.

Any help would be appreciated!

A: 

Yes, the only way to really have 'internal' classes would be to hide the headers for them. But even then, it is trivial for anyone to use those classes if they know the name of it `NSClassFromString' I would say you may want to think about re architecting it instead of using a class design style that Obj-C isn't really made for.

Without knowing more about what you are doing I can't suggest a different design though.

Joshua Weinberg
+1  A: 

There is no concept of "internal" in the same way in Obj-C. As Joshua says, the best you can do is just keep the headers for the "internal" subclasses private, documenting only the interface for the base class.

Your design is fine as far as creating an abstract base class. This design is used by Apple for "class clusters", where you're not really getting a, say, NSString or NSImage, you're getting something else that has the same interface.

The other way to accomplish this in Obj-C is by using a formal protocol:

@protocol AbstractInterface
- (void)method1;
...
@end

Then instead of passing around AbstractBaseClass *s, you pass around id<AbstractInterface>s. If your base class has zero state and no default implementations, they're equivalent.

To address your other question: each class should have its own .h and .m file. This is pretty much always true regardless of this particular context.

quixoto
A: 

The way I normally do it is to declare the interface and implementation of the internal class inside the .m file for the base class.

Of course, if the classes get big, you might need to separate them out to avoid files that are too big. If you are writing a framework, there is a mechanism to specify which headers get made public (i.e. exported to the framework's headers directory), otherwise, you just have to resort to documentation.

JeremyP
A: 

Thank you for all your answers, I have decided to make the classes public, as I will be the only one using this library at this time. I was really just wondering if I had missed something in the documentation of the Objective C language about internal classes, because you can mark variables as @package.

Richard J. Ross III