views:

5346

answers:

6

I'm originally a Java programmer who now works with Objective-C. I'd like to create an abstract class but that doesn't appear to be possible in Objective-C. Is this possible?

If not, how close to an abstract class can I get in Objective-C?

+7  A: 

from http://www.omnigroup.com/mailman/archive/macosx-dev/2004-August/053887.html

Objective-C doesn't have the abstract compiler construct like Java at this time.

So all you do is define the abstract class as any other normal class and implement methods stubs for the abstract methods that either are empty or report non-support for selector. For example...

- (id)someMethod:(SomeObject*)blah
{
     [self doesNotRecognizeSelector:_cmd];
     return nil;
}

I also do the following to prevent the initialization of the abstract class via the default initializer.

- (id)init
{
     [self doesNotRecognizeSelector:_cmd];
     [self release];
     return nil;
}
Steve918
A link is appropriate. Copying wholesale without naming the author is not.
Matthew Flaschen
I think this is a bit harsh - there is reference to the material and I think having the content here is also relevant to answering the question.
Grouchal
Agreed. Having the link is sufficient, you can look up the author there if desired. Give the guy a break!
Quinn Taylor
I hadn't thought of using -doesNotRecognizeSelector: and I kinda like this approach in some ways. Does anyone know of a way to make the compiler issue a warning for an "abstract" method created either this way or by raising an exception? That would be awesome...
Quinn Taylor
The doesNotRecognizeSelector approach prevents Apple's suggested self=[super init] pattern.
david
@david: I'm pretty sure the whole point is to raise an exception as soon as possible. Ideally it should be at compile time, but since there is no way to do that, they settled for a run time exception. This is akin to an assertion failure, which should never be raised in production code in the first place. In fact, an assert(false) might actually be better since it is clearer that this code should never run. The user can't do anything to fix it, the developer must fix it. Thus raising an exception or assertion failure here sounds like a good idea.
Senseful
+22  A: 

No there is no way to create an abstract class in Objective C.

You can mock an abstract class - by making the methods/ selectors call doesNotRecognizeSelector: and therefore raise an exception making the class unusable.

for example:

- (id)someMethod:(SomeObject*)blah
{
     [self doesNotRecognizeSelector:_cmd];
     return nil;
}

you can also do this for init.

Grouchal
I have no idea why this is downvoted.
Chuck
Nor I. Is someone just having a bad day? They're spending their reputation stupidly — this answer seemed helpful to me...
Quinn Taylor
+22  A: 

Typically, Objective-C class are abstract by convention only—if the author documents a class as abstract, just don't use it without subclassing it. There is no compile-time enforcement that prevents instantiation of an abstract class, however. In fact, there is nothing to stop a user from providing implementations of abstract methods via a category (i.e. at runtime). You can force a user to at least override certain methods by raising an exception in those methods implementation in your abstract class:

[NSException raise:NSInternalInconsistencyException 
            format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];

If the abstract class is really an interface (i.e. has no concrete method implementations), using an Objective-C protocol is the more appropriate option.

Barry Wark
And then XCode is so stupid (or flexible, as it were) that if your method actually needs to return a value, you still have to do that AFTER your raise line or you get a warning.
Yar
@Yar, I don't think this is a failing of Xcode. Virtually all statically typed languages require a return value when a function/method is declared with such. Java, C# and C++ are no different.
Barry Wark
Glad you mentioned that! I was actually thinking of Java. If you throw an UnsupportedOperationException (usually meaning, "I'll get to this method later") you do not need to return.
Yar
+4  A: 

Instead of trying to create an abstract base class, consider using a protocol (similar to a Java interface). This allows you to define a set of methods, and then accept all objects that conform to the protocol and implement the methods. For example, I can define an Operation protocol, and then have a function like this:

- (void)performOperation:(id<Operation>)op
{
   // do something with operation
}

Where op can be any object implementing the Operation protocol.

If you need your abstract base class to do more than simply define methods, you can create a regular Objective-C class and prevent it from being instantiated. Just override the - (id)init function and make it return nil or assert(false). It's not a very clean solution, but since Objective-C is fully dynamic, there's really no direct equivalent to an abstract base class.

Ben Gotow
+1  A: 

so have a look at the CocoaDev site which gives it a java comparison

http://www.cocoadev.com/index.pl?AbstractSuperClass

bruce