Subclass Objective-C class without linking with the superclass? - objective-c

I'm writing a SIMBL plugin for Spotlight, and I'm trying to create a subclass of an internal Spotlight type. While I can get headers directly from the executable using class-dump, I don't have a static library to link against, so compiling a subclass of one of those internal classes fails (even though the classes will be available at runtime). I've been following Mike Ash's instructions on subclassing classes at runtime, but it's pretty inconvenient. Is there any way to create a subclass of an Objective-C class without the superclass being available at link time?

This is entirely possible, and not actually very difficult to do. Here's a simple example with NSValue:
#interface MySubclass : NSObject
-(void) someMethod;
#end
#implementation MySubclass
+(void) load {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
class_setSuperclass(self, NSClassFromString(#"NSValue"));
#pragma clang diagnostic pop
}
-(void) someMethod {
NSLog(#"%#", [self superclass]);
}
-(const char *) objCType {
return #encode(int);
}
-(void) getValue:(void *)value {
if (value) {
*((int *) value) = 10;
}
}
#end
int main() {
MySubclass *theSubclass = [MySubclass new];
[theSubclass someMethod];
NSLog(#"%i", [theSubclass isKindOfClass:[NSValue class]]);
}
class_setSuperclass, while deprecated, still has an implementation as of OS X 10.10, and can be done after the class has been registered. I have not fully explored the effects of changing a class's superclass post the creation of an instance of that class, however, so take caution if you are to do this at any point past +load or +initialize.
This may make it difficult to call methods on super, but this could be gotten around by simply declaring a category on NSObject (or whichever superclass you choose to inherit from in your implementation).

Related

Objective-C How to force subclass to implement methods?

Another way of phrasing this question: is it possible for a subclass to be a delegate of its super class? I'm trying to make my code reusable within my app and have a situation where the subsclass needs to implement two methods for it to be functional. How can I ensure this occurs? Or what is the proper way of defining these methods?
Update
I didn't mean to imply that I want the compiler to generate flags. I just want a clean way of organizing my code. Currently I override methods of the superclass. Using that approach the superclass can call [super methodToOverride] and it works. However this doesn't feel very clean to me as there's no way to specify "these are the methods you should override" aside from putting a comment somewhere.
In obj-c, it is not possible to force subclasses to overwrite methods of its superclass. But you can raise an exception in the superclass, should it ever be called because the subclass did not implement a certain method.
But a subclass can be a delegate of its superclass, if the superclass does not implement certain methods, and you can enforce that the delegate implements these methods, if the superclass specifies the protocol, i.e. required methods, and the subclass adopts it.
If you want to force your subclass to implement methods from super class, you can do this as below:
//In super class
- (id)someMethod:(SomeObject*)bla
{
[self doesNotRecognizeSelector:_cmd];
return nil;
}
Your app will crash if subclass will not implement this method and you don't need to call
[super someMethod:bla];
There is no way to do this in compile time. However you can raise an exception in the base class.
Something like this:
#throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:#"You must override %# in a subclass", NSStringFromSelector(_cmd)]
userInfo:nil];
If your question is "how can I get the compiler to flag that a certain class doesn't implement a certain function" then I would say
Define a protocol with non-optional methods -- "By default, all methods declared in a protocol are required methods. This means that any class that conforms to the protocol must implement those methods."
Define a class ("stub") that declares it implements the protocol
Now when a subclass of your stub class is written, the compiler will flag it as an error if the mandatory method(s) aren't implemented
I know that it's awful, but supposed that you need to do this since your 3rdParty SDK requires this design pattern, you could use a Factory pattern:
Supposed then to have the base class MyParentAPIClient and two sub classes like MyFacebookAPIClient and MyGooglePlusAPIClient and that you do something like
self.myAPIClient = [MyParentAPIClient alloc] initWithAPIKey:apiKey];
and that you have defined
##interface MyParentAPIClient : NSObject {
}
-(void)callAPI;
#end
and you have override this in the two subclasses
#implementation MyFacebookAPIClient
-(void)callAPI {
[super callAPI];
// do something specific for this api client
}
#end
and
#implementation MyGooglePlusAPIClient
-(void)callAPI {
[super callAPI];
// do something specific for this api client
}
#end
Then you are doing in your controller
[self.myAPIClient callAPI];
but the super class MyParentAPIClient method is being called.
Now you could do a factory in the base class like:
-(void)callAPI {
if([self isKindOfClass:[MyFacebookAPIClient class]]) {
[((MyFacebookAPIClient*)self) callAPI];
} else if([self isKindOfClass:[MyGooglePlusAPIClient class]]) {
[((MyGooglePlusAPIClient*)self) callAPI];
}
}
Of course this have a downside that is to do not call the super in the sub classes that now become:
#implementation MyFacebookAPIClient
-(void)callAPI {
// [super callAPI]; the factory method called that
// do something specific for this api client
}
#end
and
#implementation MyGooglePlusAPIClient
-(void)callAPI {
// [super callAPI]; being called in the factory
// do something specific for this api client
}
#end
The good news is that there is no change in the methods calls since as soon as you call from the controller:
[self.myAPIClient callAPI];
You will have the calls
[MyParentAPIClient callAPI]; // parent class
[MyFacebookAPIClient callAPI]; // sub class
The other downside is that the parent class must known the subclass instances.
Now if we take a look at the factory:
if([self isKindOfClass:[MyFacebookAPIClient class]]) {
[((MyFacebookAPIClient*)self) callAPI];
} else if([self isKindOfClass:[MyGooglePlusAPIClient class]]) {
[((MyGooglePlusAPIClient*)self) callAPI];
}
}
we could make it better like in several way. Take a look at Dynamic type cast from id to class in objective c and Is there an equivalent to C++'s dynamic cast in Objective-C? or Objective-C dynamic_cast?
Good luck!
The UIGestureRecognizerSubclass.h pattern from UIKit is worth a look, that has all the protected methods that should be overridden and that header is not in the framework include, it is only included in subclasss' .m files. Also, nowadays you can tag methods with NS_REQUIRES_SUPER to require overrides to call super, however it can only be used in interfaces, not protocols so that might influence your design.
For super advanced code, NSAccessibilityProtocols.h in AppKit uses a protocol tag to require subclasses to re-implement methods, even if already implemented by a superclass. Here is an example of that you can paste right into in header in your currently open Xcode project:
NS_PROTOCOL_REQUIRES_EXPLICIT_IMPLEMENTATION
#protocol Protocol
#property (readonly) id theWorstOfTimes;
// -(void)testMethod; // uncomment to test problem
#end
// In this example, ClassA adopts the protocol.
#interface ClassA : NSObject <Protocol>
#property (readonly) id theWorstOfTimes;
#end
#implementation ClassA
- (id)theWorstOfTimes{
return nil; // default implementation does nothing
}
-(void)testMethod{}
#end
// This class subclasses ClassA (which also adopts 'Protocol').
#interface ClassB : ClassA <Protocol>
#end
#implementation ClassB // expected-warning {{property 'theWorstOfTimes' requires method 'theWorstOfTimes' to be defined - use #synthesize, #dynamic or provide a method implementation in this class implementation}}
#end
In Xcode you'll see a yellow line at ClassB's expected-warning that the property method is missing. NS_PROTOCOL_REQUIRES_EXPLICIT_IMPLEMENTATION is just a macro for __attribute__((objc_protocol_requires_explicit_implementation)) and this code sample is modified from the test harness of that feature here.
Although this looks great there is a slight problem. Currently this only works for methods that implement protocols, it used to work also for methods but a bug has been introduced in 2014 via a misunderstanding on the purpose of this feature and thus now it is limited to property methods. I have emailed the author to make them aware so hopefully it changed back to its original and proper behavior. To test the bug you can uncomment the method in the protocol and you will see there is no warning in ClassB. Hopefully you can change some of your methods to read-only properties to at least get some use out of it. On the plus side when Xcode offers to "Fix" the issue it does add stubs for the missing methods.
Here is some documentation on NS_PROTOCOL_REQUIRES_EXPLICIT_IMPLEMENTATION:
ImplementingAccessibilityforCustomControls
nsaccessibilitybutton
If you used this then pat yourself on the back for becoming an ObjC expert if you weren't already!

Programmatically creating new instance method to track message sending

I want to design a class (TrackingClass) that would be in charge of tracking the calls to some methods of an other class (TrackedClass), i.e. of setting up the method swizzling from what I understood.
So let's say I load up an array with #selectors of the instance methods of TrackedClass i'm interested in.
Here is the pseudo-code I would like to run :
#implementation BCTrackedClass
-(void)doA
{
}
#end
and
#implementation BCTrackingClass
#import "BCTrackingClass.h"
#import "BCTrackedClass.h"
#include <objc/runtime.h>
#include <objc/objc-runtime.h>
#implementation BCTrackingClass
void myMethodIMP(id self, SEL _cmd);
void myMethodIMP(id self, SEL _cmd)
{
//NSLog(#"_cmd : %#",NSStringFromSelector(_cmd));
[BCTrackingClass logCallForMethod:NSStringFromSelector(_cmd)];
objc_msgSend(self,
NSSelectorFromString([NSString stringWithFormat:#"tracked%#",NSStringFromSelector(_cmd)]));
}
+(void)setUpTrackingForClass:(Class)aClass andMethodArray:(NSArray*)anArray //Array of selectorsStrings of methods to track
{
for (NSString* selectorString in anArray)
{
SEL selector = NSSelectorFromString(selectorString);
SEL trackedSelector = NSSelectorFromString([NSString stringWithFormat:#"tracked%#",selectorString]);
class_addMethod(aClass,
trackedSelector,
(IMP) myMethodIMP, "v#:");
//Swizzle the original method with the tracked one
Method original = class_getInstanceMethod(aClass,
selector);
Method swizzled = class_getInstanceMethod(aClass,
trackedSelector);
method_exchangeImplementations(original, swizzled);
}
}
+(void)logCallForMethod:(NSString*)aSelectorString
{
NSLog(#"%#",aSelectorString);
}
#end
Theoretically, I'm just missing the bit of code where I could effectively create this new instance method trackedSelector. Can I achieve that ?
Edit
I updated the code with some new piece of information, am I getting closer ?
Edit 2
I set up a Github repository with a Demo application if people want to dynamically try out their ideas.
Source : BCTrackingClass on Github
Edit 3
I finally come up with a working version of the code (cf Github repo, or just above). My next problem is : I want my class to be instance based (currently, all my methods are class methods), so that I can assign a property #property NSMutableDictionnary* to instances of the class for call logging.
I'm not sure how to achieve that. Any ides ?
Do you want to do it for all instances of all objects of that class?
for some selectors or all of them?
...
If what you want is to track specific instances, then the simplest route is to use isa swizzling, doing that, more or less (the code is absolutely untested)
#interface ClassTracker
+ (void)trackObject:(id)object;
#end
static const char key;
#implementation ClassTracker
+ (void)trackObject:(id)object
{
objc_setAssociatedObject(object, &key, [object class], OBJC_ASSOCIATION_ASSIGN);
object_setClass(object, [ClassTracker class]);
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
Class aClass = objc_getAssociatedObject(self, &key);
return [aClass instanceMethodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
Class aClass = objc_getAssociatedObject(self, &key);
// do your tracing here
object_setClass(self, aClass);
[invocation invoke];
object_setClass(self, [ClassTracker class]);
}
// dealloc is magical in the sense that you really want to undo your hooking
// and not resume it ever!
- (void)dealloc
{
Class aClass = objc_getAssociatedObject(self, &key);
object_setClass(self, aClass);
[self dealloc];
}
#end
If it's used for reverse engineering or debug purposes, that should (with minor adaptations) do the trick.
If you intend that to be fast, then you have to do instance method swizzling, knowing their type and so forth.
My "solution" has the drawback that it will only trace entering calls, IOW if a selector calls other ones, since the isa swizzling is paused to recurse the call, then you don't see the new ones until you restore the isa swizzling.
There may be a way to forward the invocation to the original class, without undoing isa swizzling, but I reckon I was too lazy to search for it.

Release method not recognized at runtime (non Cocoa)

I'm a newbie to Objective-C but have extensive experience in C and C++. The first thing I have noticed is that there is a real void in basic tutorials out there as all assume you are developing for the iPhone or Mac and using Cocoa. I'm not using Cocoa or Gnustep. To the point:
As a simple example to get started I'm trying to wrap the C's File I/O functionality. My code starts as
File.h
#include <objc/Object.h>
#include <stdio.h>
#interface File:Object
{
FILE *pFile;
char *path;
}
#property FILE *pFile;
#property char *path;
- (void)new;
- (void)OpenReadText:(const char*)var1;
- (void)release;
#end
And File.m
#include "File.h"
#implementation File
#synthesize pFile, path;
- (void)new
{
self = [super init];
}
- (void)release
{
fclose(pFile);
[super release];
}
- (void)OpenReadText:(char*)var1
{
path = var1;
pFile = fopen(path,"r");
}
#end
Then main.m
#include <stdio.h>
#import <objc/Object.h>
#include "File.h"
int main(void) {
File *Fileobj = [File new];
[Fileobj OpenReadText:"File.h"];
[Fileobj release];
}
The compiler gives me a warning that my object "may not respond to '-release'". Then when running the program is results in a runtime error: "does not recognize release. This application has requested the Runtime to terminate" .. and so on.
I'm guessing I'm making a simple newbie error, but where? Or perhaps there is something missing? I'm hoping someone can point me in the right direction here. Thanks.
If this qst has been asked already then a reference would do too. I did try to find a reference but no luck.
FOLLOW UP:
changed release method to
- (void)release
{
fclose(pFile);
[super free];
}
and it appeared to work. Apparently free is recognized in object.h.
As others have said it is unusual to use Objective-C without the Foundation frameworks. However, the Object class should implement release, retain etc. The Object class included (but not used) in Apple's Objective-C Runtime certainly contains these basic methods.
Assuming your Object class does contain these basic methods there are a couple of problems with your class as implemented.
First, you have created a new instance method which simply calls [super init]. The new method by convention is a class method which is shorthand for calling alloc and init to create and initialise an object. new is defined in Apple's Object class. It is implemented as:
+ (id)new
{
id newObject = (*_alloc)((Class)self, 0);
Class metaClass = self->isa;
if (class_getVersion(metaClass) > 1)
return [newObject init];
else
return newObject;
}
Note that this method is a class method, signified by the + instead of the -. GNUStep implements new as follows:
+ new
{
return [[self alloc] init];
}
The idiomatic way to use new would be:
File *obj = [File new];
This is in fact what you have done, however, this is calling the class method new not your instance method new.
If you wanted to call your new method you'd have to call:
File *obj = [[File alloc] new];
but as others have stated you'd need to return your object. Removing your new method would have no effect on your implementation as it isn't currently being called.
Secondly, you have placed your call to fclose in your overriden release method. This is wrong, certainly in Apple's implementation of Object anyway, GNUstep appears to be different. release could get called multiple times on a single instance of an object. retain and release are used to increment/decrement the objects retain count. Only when the retain count reaches zero should the file handle be closed. Normally, within Foundation you'd place the call to fclose in a dealloc method. dealloc is Objective-C's destructor method. The dealloc should look something like:
- (void)dealloc
{
fclose(pFile);
[super dealloc];
}
However, dealloc doesn't appear to be implemented in either Apple's or GNUstep's Object class. There is, as you point out in your question a free method which seems to be a destructor.
It would appear that replacing the above dealloc method with an equivalent free method would work as a destructor, e.g.:
- (void)free
{
fclose(pFile);
[super free];
}
Apple's implementation of Object contains retain and release methods but the GNUstep implementation does not. Neither implementation contains a dealloc method.
The implementations of Object.m and NSObject.m for Apple and GNUstep can be found at the following locations:
Apple Object.m: http://opensource.apple.com/source/objc4/objc4-532.2/runtime/Object.m
GNUstep Object.m: https://github.com/gnustep/gnustep-libobjc/blob/master/Object.m
Apple NSObject.mm: http://opensource.apple.com/source/objc4/objc4-532.2/runtime/NSObject.mm
GNUstep NSObject.m: https://github.com/gnustep/gnustep-base/blob/master/Source/NSObject.m
Is release defined on class Object? If it is not, then your call to
[super release];
will not work. (In cocoa, release is a member of NSObject; your Object class may or may not have it, and in fact the retain/release reference counting might not be there at all.)
You should confirm that your base class includes all methods called via super.
As #xlc0212 pointed out, the reference counting style of memory management is included in NSObject.
NSObject is a part of CoreFoundation library for Cocoa, CocoaTouch and GnuStep. I would say you need to link to CoreFoundation.
One book that I've read and focuses on pure Objective-C (not necessarily Cocoa) is "Programming in Objective-C 2.0" by Steven G Kochan.

Delegation to multiple objects

Is there any way to delegate to two objects at a time in Objective-C? I know that delegation pattern implies one response at a time and for multiple listeners and broadcasting there is notification center but notification does not return any value.
If I have a heavily network-based iOS project and need to delegate to multiple listeners and required to return values from them, in this scenario what approach should be the best?
In every class the delegate is one, so one delegate is informed about the event. But nothing forbids you to declare a class with a set of delegates.
Or use Observation instead. A class may be observed by multiple classes.
Example
As requested from the OP, since also some code would be useful, here is a way of doing it:
#interface YourClass()
#property (nonatomic, strong, readwrite) NSPointerArray* delegates;
// The user of the class shouldn't even know about this array
// It has to be initialized with the NSPointerFunctionsWeakMemory option so it doesn't retain objects
#end
#implementation YourClass
#synthesize delegates;
... // other methods, make sure to initialize the delegates set with alloc-initWithOptions:NSPointerFunctionsWeakMemory
- (void) addDelegate: (id<YourDelegateProtocol>) delegate
{
[delegates addPointer: delegate];
}
- (void) removeDelegate: (id<YourDelegateProtocol>) delegate
{
// Remove the pointer from the array
for(int i=0; i<delegates.count; i++) {
if(delegate == [delegates pointerAtIndex: i]) {
[delegates removePointerAtIndex: i];
break;
}
} // You may want to modify this code to throw an exception if no object is found inside the delegates array
}
#end
This is a very simple version, you can do it in another way. I don't suggest to make public the delegates set, you never know how it could be used, and you can get an inconsistent state, specially with multithreading. Also, when you add/remove a delegate you may need to run additional code, so that's why making the delegates set private.
You may also a lot of other methods like delegatesCount for example.
PS: The code has been edited to be a NSPointerArray instead of a NSMutableSet, because as stated in the comments a delegate should be held with a weak pointer to avoid retain cycles.
In addition to Ramys answer you could use a [NSHashTable weakObjectsHashTable] instead of a
NSMutableSet. This would keep only a weak reference to your delegates and prevents you from running into memory leaks.
You will get the same behavior you already know from standard weak delegates #property (nonatomic, weak) id delegate;
#interface YourClass()
#property (nonatomic, strong) NSHashTable *delegates;
#end
#implementation YourClass
- (instancetype)init
{
self = [super init];
if (self) {
_delegates = [NSHashTable weakObjectsHashTable];
}
return self;
}
- (void) addDelegate: (id<YourDelegateProtocol>) delegate
{
// Additional code
[_delegates addObject: delegate];
}
// calling this method is optional, because the hash table will automatically remove the delegate when it gets released
- (void) removeDelegate: (id<YourDelegateProtocol>) delegate
{
// Additional code
[_delegates removeObject: delegate];
}
#end
Robbie Hanson wrote a multicast delegate implementation. Looks like what you need. He talks about it in more detail here, and how it is used in the XMPPFramework. He has some good discussion about one of the main problems which is how to handle the case where the multiple delegates implement a given method who's return value determines the class' behaviour (and the multiple delegates return different values). Relevant bits:
What is a MulticastDelegate?
The xmpp framework needs to support an unlimited number of extensions.
This includes the official extensions that ship with the framework, as
well as any number of extensions or custom code you may want to plug
into the framework. So the traditional delegate pattern simply won't
work. XMPP modules and extensions need to be separated into their own
separate classes, yet each of these classes needs to receive delegate
methods. And the standard NSNotification architecture won't work
either because some of these delegates require a return variable.
(Plus it's really annoying to extract parameters from a notification's
userInfo dictionary.)
So a MulticastDelegate allows you to plug into the framework using the
standard delegate paradigm, but it allows multiple classes to receive
the same delegate notifications. The beauty of this is that you don't
have to put all your xmpp handling code in a single class. You can
separate your handling into multiple classes, or however you see fit.
If you're writing the function that will call the delegates, you can have as many as you want. But if you're using a class (that you can't change) that calls the delegates, then you can't have more delegates than the class supports.
You could, if it worked out for you, have one delegate call another. Set up the first delegate so it will call the second delegate (whose pointer is stored in the first delegate object). This can be simple, with it pre-defined as to which calls are "passed on", or quite complex, using the dynamic call mechanisms of Objective-C.
One delegate can be setting for only one object but it's possible to store delegates in array.
Variant of Ramy Al Zuhouri is good but I want to say that it may be a problem to release delegates from array because NSArray (like NSMutableArray) classes retain all added objects but delegate in most cases is an assign property without retainCount. Retaining the delegate can bring to consequences that class with delegate implementation will have retainCount + 1.
Solution of this is store delegates in NSMutableArray like pointers to delegate methods.
I'm using singletone class with delegate header.
//YourClass.h file
#protocol YourDelegateProtocol <NSObject>
-(void)delegateMethod;
#end
#interface YourClass : NSObject
+(YourClass *)sharedYourClass;
- (void) addDelegate: (id<YourDelegateProtocol>) delegate;
- (void) removeDelegate: (id<YourDelegateProtocol>) delegate
#end
//YourClass.m file
#interface YourClass()
#property (nonatomic, retain) NSMutableArray *delegates;
-(void)runAllDelegates;
#end
#implementation YourClass
#synthesize delegates = _delegates;
static YourClass *sharedYourClass = nil;
+(YourClass *)sharedYourClass {
if (!sharedYourClass || sharedYourClass == nil) {
sharedYourClass = [YourClass new];
sharedYourClass.delegates = [NSMutableArray array];
}
return sharedYourClass;
}
-(void)addDelegate: (id<YourDelegateProtocol>) delegate{
NSValue *pointerToDelegate = [NSValue valueWithPointer:delegate];
[_delegates addObject: pointerToDelegate];
}
-(void)removeDelegate: (id<YourDelegateProtocol>) delegate{
NSValue *pointerToDelegate = [NSValue valueWithPointer:delegate];
[_delegates removeObject: pointerToDelegate];
}
-(void)runAllDelegates{
//this method will run all delegates in array
for(NSValue *val in sharedYourClass.delegates){
id<YourDelegateProtocol> delegate = [val pointerValue];
[delegate delegateMethod];
}
}
-(void)dealloc{
sharedYourClass.delegates =nil;
[sharedYourClass release], sharedYourClass =nil;
[super dealloc];
}
#end
//YourClassWithDelegateImplementation.h file
#include "YourClass.h"
#interface YourClassWithDelegateImplementation : NSObject <YourDelegateProtocol>
#end
//YourClassWithDelegateImplementation.m file
#implementation YourClassWithDelegateImplementation
-(id)init{
self = [super init];
if(self){
//...your initialization code
[[YourClass sharedYourClass] addDelegate:self];
}
return self;
}
-(void)delegateMethod{
//implementation of delegate
}
-(void)dealloc{
[[YourClass sharedYourClass] removeDelegate:self];
[super dealloc];
}
#end
If you want to call callbacks for classes B and C from a class A with only one delegate, you could create a delegate wrapper DWrap which has references to the classes B and C. Then class A calls the callbacks on B and C through DWrap.

Creating an abstract class in Objective-C

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?
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 your method returns a value, it's a bit easier to use
#throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:#"You must override %# in a subclass", NSStringFromSelector(_cmd)]
userInfo:nil];
as then you don't need to add a return statement from the method.
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.
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.
Just riffing on #Barry Wark's answer above (and updating for iOS 4.3) and leaving this for my own reference:
#define mustOverride() #throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:#"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] userInfo:nil]
#define methodNotImplemented() mustOverride()
then in your methods you can use this
- (void) someMethod {
mustOverride(); // or methodNotImplemented(), same thing
}
Notes: Not sure if making a macro look like a C function is a good idea or not, but I'll keep it until schooled to the contrary. I think it's more correct to use NSInvalidArgumentException (rather than NSInternalInconsistencyException) since that's what the runtime system throws in response to doesNotRecognizeSelector being called (see NSObject docs).
The solution I came up with is:
Create a protocol for everything you want in your "abstract" class
Create a base class (or maybe call it abstract) that implements the protocol. For all the methods you want "abstract" implement them in the .m file, but not the .h file.
Have your child class inherit from the base class AND implement the protocol.
This way the compiler will give you a warning for any method in the protocol that isn't implemented by your child class.
It's not as succinct as in Java, but you do get the desired compiler warning.
From the Omni Group mailing list:
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;
}
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.
This thread is kind of old, and most of what I want to share is already here.
However, my favorite method is not mentioned, and AFAIK there’s no native support in the current Clang, so here I go…
First, and foremost (as others have pointed out already) abstract classes are something very uncommon in Objective-C — we usually use composition (sometimes through delegation) instead. This is probably the reason why such a feature doesn’t already exist in the language/compiler — apart from #dynamic properties, which IIRC have been added in ObjC 2.0 accompanying the introduction of CoreData.
But given that (after careful assessment of your situation!) you have come to the conclusion that delegation (or composition in general) isn’t well suited to solving your problem, here’s how I do it:
Implement every abstract method in the base class.
Make that implementation [self doesNotRecognizeSelector:_cmd];…
…followed by __builtin_unreachable(); to silence the warning you’ll get for non-void methods, telling you “control reached end of non-void function without a return”.
Either combine steps 2. and 3. in a macro, or annotate -[NSObject doesNotRecognizeSelector:] using __attribute__((__noreturn__)) in a category without implementation so as not to replace the original implementation of that method, and include the header for that category in your project’s PCH.
I personally prefer the macro version as that allows me to reduce the boilerplate as much as possible.
Here it is:
// Definition:
#define D12_ABSTRACT_METHOD {\
[self doesNotRecognizeSelector:_cmd]; \
__builtin_unreachable(); \
}
// Usage (assuming we were Apple, implementing the abstract base class NSString):
#implementation NSString
#pragma mark - Abstract Primitives
- (unichar)characterAtIndex:(NSUInteger)index D12_ABSTRACT_METHOD
- (NSUInteger)length D12_ABSTRACT_METHOD
- (void)getCharacters:(unichar *)buffer range:(NSRange)aRange D12_ABSTRACT_METHOD
#pragma mark - Concrete Methods
- (NSString *)substringWithRange:(NSRange)aRange
{
if (aRange.location + aRange.length >= [self length])
[NSException raise:NSInvalidArgumentException format:#"Range %# exceeds the length of %# (%lu)", NSStringFromRange(aRange), [super description], (unsigned long)[self length]];
unichar *buffer = (unichar *)malloc(aRange.length * sizeof(unichar));
[self getCharacters:buffer range:aRange];
return [[[NSString alloc] initWithCharactersNoCopy:buffer length:aRange.length freeWhenDone:YES] autorelease];
}
// and so forth…
#end
As you can see, the macro provides the full implementation of the abstract methods, reducing the necessary amount of boilerplate to an absolute minimum.
An even better option would be to lobby the Clang team to providing a compiler attribute for this case, via feature requests. (Better, because this would also enable compile-time diagnostics for those scenarios where you subclass e.g. NSIncrementalStore.)
Why I Choose This Method
It get’s the job done efficiently, and somewhat conveniently.
It’s fairly easy to understand. (Okay, that __builtin_unreachable() may surprise people, but it’s easy enough to understand, too.)
It cannot be stripped in release builds without generating other compiler warnings, or errors — unlike an approach that’s based on one of the assertion macros.
That last point needs some explanation, I guess:
Some (most?) people strip assertions in release builds. (I disagree with that habit, but that’s another story…) Failing to implement a required method — however — is bad, terrible, wrong, and basically the end of the universe for your program. Your program cannot work correctly in this regard because it is undefined, and undefined behavior is the worst thing ever. Hence, being able to strip those diagnostics without generating new diagnostics would be completely unacceptable.
It’s bad enough that you cannot obtain proper compile-time diagnostics for such programmer errors, and have to resort to at-run-time discovery for these, but if you can plaster over it in release builds, why try having an abstract class in the first place?
Using #property and #dynamic could also work. If you declare a dynamic property and don't give a matching method implementation, everything will still compile without warnings, and you'll get an unrecognized selector error at runtime if you try to access it. This essentially the same thing as calling [self doesNotRecognizeSelector:_cmd], but with far less typing.
In Xcode (using clang etc) I like to use __attribute__((unavailable(...))) to tag the abstract classes so you get an error/warning if you try and use it.
It provides some protection against accidentally using the method.
Example
In the base class #interface tag the "abstract" methods:
- (void)myAbstractMethod:(id)param1 __attribute__((unavailable("You should always override this")));
Taking this one-step further, I create a macro:
#define UnavailableMacro(msg) __attribute__((unavailable(msg)))
This lets you do this:
- (void)myAbstractMethod:(id)param1 UnavailableMacro(#"You should always override this");
Like I said, this is not real compiler protection but it's about as good as your going to get in a language that doesn't support abstract methods.
The answer to the question is scattered around in the comments under the already given answers. So, I am just summarising and simplifying here.
Option1: Protocols
If you want to create an abstract class with no implementation use 'Protocols'. The classes inheriting a protocol are obliged to implement the methods in the protocol.
#protocol ProtocolName
// list of methods and properties
#end
Option2: Template Method Pattern
If you want to create an abstract class with partial implementation like "Template Method Pattern" then this is the solution.
Objective-C - Template methods pattern?
Another alternative
Just check the class in the Abstract class and Assert or Exception, whatever you fancy.
#implementation Orange
- (instancetype)init
{
self = [super init];
NSAssert([self class] != [Orange class], #"This is an abstract class");
if (self) {
}
return self;
}
#end
This removes the necessity to override init
(more of a related suggestion)
I wanted to have a way of letting the programmer know "do not call from child" and to override completely (in my case still offer some default functionality on behalf of the parent when not extended):
typedef void override_void;
typedef id override_id;
#implementation myBaseClass
// some limited default behavior (undesired by subclasses)
- (override_void) doSomething;
- (override_id) makeSomeObject;
// some internally required default behavior
- (void) doesSomethingImportant;
#end
The advantage is that the programmer will SEE the "override" in the declaration and will know they should not be calling [super ..].
Granted, it is ugly having to define individual return types for this, but it serves as a good enough visual hint and you can easily not use the "override_" part in a subclass definition.
Of course a class can still have a default implementation when an extension is optional. But like the other answers say, implement a run-time exception when appropriate, like for abstract (virtual) classes.
It would be nice to have built in compiler hints like this one, even hints for when it is best to pre/post call the super's implement, instead of having to dig through comments/documentation or... assume.
If you are used to the compiler catching abstract instantiation violations in other languages, then the Objective-C behavior is disappointing.
As a late binding language it is clear that Objective-C cannot make static decisions on whether a class truly is abstract or not (you might be adding functions at runtime...), but for typical use cases this seems like a shortcoming. I would prefer the compiler flat-out prevented instantiations of abstract classes instead of throwing an error at runtime.
Here is a pattern we are using to get this type of static checking using a couple of techniques to hide initializers:
//
// Base.h
#define UNAVAILABLE __attribute__((unavailable("Default initializer not available.")));
#protocol MyProtocol <NSObject>
-(void) dependentFunction;
#end
#interface Base : NSObject {
#protected
__weak id<MyProtocol> _protocolHelper; // Weak to prevent retain cycles!
}
- (instancetype) init UNAVAILABLE; // Prevent the user from calling this
- (void) doStuffUsingDependentFunction;
#end
//
// Base.m
#import "Base.h"
// We know that Base has a hidden initializer method.
// Declare it here for readability.
#interface Base (Private)
- (instancetype)initFromDerived;
#end
#implementation Base
- (instancetype)initFromDerived {
// It is unlikely that this becomes incorrect, but assert
// just in case.
NSAssert(![self isMemberOfClass:[Base class]],
#"To be called only from derived classes!");
self = [super init];
return self;
}
- (void) doStuffUsingDependentFunction {
[_protocolHelper dependentFunction]; // Use it
}
#end
//
// Derived.h
#import "Base.h"
#interface Derived : Base
-(instancetype) initDerived; // We cannot use init here :(
#end
//
// Derived.m
#import "Derived.h"
// We know that Base has a hidden initializer method.
// Declare it here.
#interface Base (Private)
- (instancetype) initFromDerived;
#end
// Privately inherit protocol
#interface Derived () <MyProtocol>
#end
#implementation Derived
-(instancetype) initDerived {
self= [super initFromDerived];
if (self) {
self->_protocolHelper= self;
}
return self;
}
// Implement the missing function
-(void)dependentFunction {
}
#end
Probably this kind of situations should only happen at development time, so this might work:
- (id)myMethodWithVar:(id)var {
NSAssert(NO, #"You most override myMethodWithVar:");
return nil;
}
You can use a method proposed by #Yar (with some modification):
#define mustOverride() #throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:#"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] userInfo:nil]
#define setMustOverride() NSLog(#"%# - method not implemented", NSStringFromClass([self class])); mustOverride()
Here you will get a message like:
<Date> ProjectName[7921:1967092] <Class where method not implemented> - method not implemented
<Date> ProjectName[7921:1967092] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[<Base class (if inherited or same if not> <Method name>] must be overridden in a subclass/category'
Or assertion:
NSAssert(![self respondsToSelector:#selector(<MethodName>)], #"Not implemented");
In this case you will get:
<Date> ProjectName[7926:1967491] *** Assertion failure in -[<Class Name> <Method name>], /Users/kirill/Documents/Projects/root/<ProjectName> Services/Classes/ViewControllers/YourClass:53
Also you can use protocols and other solutions - but this is one of the simplest ones.
Cocoa doesn’t provide anything called abstract. We can create a class abstract which gets checked only at runtime, and at compile time this is not checked.
I usually just disable the init method in a class that I want to abstract:
- (instancetype)__unavailable init; // This is an abstract class.
This will generate an error at compile time whenever you call init on that class. I then use class methods for everything else.
Objective-C has no built-in way for declaring abstract classes.
Changing a little what #redfood suggested by applying #dotToString's comment, you actually have the solution adopted by Instagram's IGListKit.
Create a protocol for all the methods that make no sense to be defined in the base (abstract) class i.e. they need specific implementations in the children.
Create a base (abstract) class that does not implement this protocol. You can add to this class any other methods that make sense to have a common implementation.
Everywhere in your project, if a child from AbstractClass must be input to or output by some method, type it as AbstractClass<Protocol> instead.
Because AbstractClass does not implement Protocol, the only way to have an AbstractClass<Protocol> instance is by subclassing. As AbstractClass alone can't be used anywhere in the project, it becomes abstract.
Of course, this doesn't prevent unadvised developers from adding new methods referring simply to AbstractClass, which would end up allowing an instance of the (not anymore) abstract class.
Real world example: IGListKit has a base class IGListSectionController which doesn't implement the protocol IGListSectionType, however every method that requires an instance of that class, actually asks for the type IGListSectionController<IGListSectionType>. Therefore there's no way to use an object of type IGListSectionController for anything useful in their framework.
In fact, Objective-C doesn't have abstract classes, but you can use Protocols to achieve the same effect. Here is the sample:
CustomProtocol.h
#import <Foundation/Foundation.h>
#protocol CustomProtocol <NSObject>
#required
- (void)methodA;
#optional
- (void)methodB;
#end
TestProtocol.h
#import <Foundation/Foundation.h>
#import "CustomProtocol.h"
#interface TestProtocol : NSObject <CustomProtocol>
#end
TestProtocol.m
#import "TestProtocol.h"
#implementation TestProtocol
- (void)methodA
{
NSLog(#"methodA...");
}
- (void)methodB
{
NSLog(#"methodB...");
}
#end
A simple example of creating an abstract class
// Declare a protocol
#protocol AbcProtocol <NSObject>
-(void)fnOne;
-(void)fnTwo;
#optional
-(void)fnThree;
#end
// Abstract class
#interface AbstractAbc : NSObject<AbcProtocol>
#end
#implementation AbstractAbc
-(id)init{
self = [super init];
if (self) {
}
return self;
}
-(void)fnOne{
// Code
}
-(void)fnTwo{
// Code
}
#end
// Implementation class
#interface ImpAbc : AbstractAbc
#end
#implementation ImpAbc
-(id)init{
self = [super init];
if (self) {
}
return self;
}
// You may override it
-(void)fnOne{
// Code
}
// You may override it
-(void)fnTwo{
// Code
}
-(void)fnThree{
// Code
}
#end
Can't you just create a delegate?
A delegate is like an abstract base class in the sense that you say what functions need to be defined, but you don't actually define them.
Then whenever you implement your delegate (i.e abstract class) you are warned by the compiler of what optional and mandatory functions you need to define behavior for.
This sounds like an abstract base class to me.