views:

78

answers:

4

Sorry if this is a repost but I couldn't quite search for it because I can't explain it in a few words. I have a super class with lots of methods but they will always (not all of them) be subclassed. From the super I need to run those methods. I could either leave the methods in super empty or I could just not type them in super but call them anyway like so [self myMethod] and it will call my subclassed method even if it doesn't exist in super. This works but Xcode gives me an error though. 'superclass' may not respond to '-subclassmethod'

What should I do so I won't get the warnings?

+4  A: 

I prefer to define the unimplemented methods in the superclass like this:

@interface GLObject : NSObject {}
- (id)someSubclassProvidedMethod;
@end

@implementation GLObject
- (id)someSubclassProvidedMethod {
  [self doesNotRecognizeSelector: _cmd];
}
@end

It's almost entirely redundant, because the Objective-C runtime would eventually call -doesNotRecognizeSelector: if I didn't define the method at all. But because I do define it, it's in the class's interface which both keeps the compiler happy and provides me with some documentation.

Graham Lee
Just don't forget to document the methods in the header as being abstract (intended to be overridden).
Peter Hosey
This sounds great but my methods are non-void and the compile will still nag about the return value.
Michael Matheus
@Michael then return some pointless value after calling `-doesNotRecognizeSelector:`, or mark the method as non-returning.
Graham Lee
By 'marking it as non-returning', do you mean (void)myMethod instead of (NSString *)myMethod?
Michael Matheus
I do almost the same thing but instead of calling doesNotRecognizeSelector: I usually do something like NSAssert2( FALSE, @"'%@' is abstract and must be overridden for '%@'", NSStringFromSelector(_cmd), self);
Jason Coco
@Michael no, I mean `__attribute__ ((noreturn))`.
Graham Lee
@Graham sorry to get back to you but, I added the noreturn attribute in the declaration of my method like this -(NSString *)myMethod __attribute__ ((noreturn)); and now I get another warning saying 'noreturn function does return' while everything there is in the method is just the doesNotRecognizeSelector call.
Michael Matheus
@michael oh, that doesn't work then :-(
Graham Lee
A: 

I lately like using NSAssert for this task:

- (BOOL)proceedForVersion:(int)versionInteger
{
    NSAssert(false, @"This method needs to be overridden in a subclass of iMBApertureAbstractParser");

    return NO;
}
Pierre Bernard
Good idea. A `#define` for this would prove useful.
Jonathan Sterling
+1  A: 

Rather than the superclass, you could declare the methods in a protocol, what is called a "interface" in other languages.

@protocol MyProtocol
-(id)myMethodWith:(id)arg;
@end

Change the type declaration of the variables to declare that the object conforms to the protocol.

-(id)doStuffWith:(SuperClass <MyProtocol> *)aThing and:(id)another {
    return [aThing myMethodWith:another]
}

Note that you won't be able to pass an instance of your SuperClass to doStuffWith:and:, since it won't implement MyProtocol, but it sounds like that's what you want.

outis
+1  A: 

My solution was a little weird, but here it is:

@protocol JSDog <NSObject>
- (void)yipe;
@end

@interface JSDog : NSObject
@end

@implementation JSDog

+ (void)initialize {
  if ([self isSubclassOfClass:[JSDog class]] && ![self conformsToProtocol:@protocol(JSDog)]) {
    NSAssert(false, @"Subclasses of JSDog must conform to <JSDog>.");
  }
}

@end

Having a protocol with the same name as a class is precedented in NSObject. Because methods in a formal protocol a by default @required, you will be protected on both ends: in compile-time, if your JSDog subclass purports to conform to <JSDog>, but doesn't implement -yipe, you will receive an error; at runtime, if your subclass does not claim to conform with <JSDog>, you will receive a warning when the subclass is instantiated.

Jonathan Sterling
Surely a bit weird. But cool.
Pierre Bernard