Cascading delegates and "Code That Doesn't Do What It Says" - objective-c

I've been searching around Apple's delegation and protocol documentation for an answer to this, but after more than a day I've decided to give up and let you guys have a shot at it. I have three classes: HTTPManager, LoginManager, and FetchManager. You can probably guess what these classes do, but to be explicit...
HTTPManager - Wraps NSURLConnection and provides a simple interface for LoginManager and FetchManager to do HTTP requests with authentication.
LoginManager / FetchManager - Basically the same class, but they respond to HTTPManager's messages differently.
HTTPManager expects a delegate to implement the HTTPManagerDelegate protocol and both LoginManager and FetchManager do this. The Login- and FetchManager classes also provide a protocol for my application delegate so that the data can make its way all the way back to the user interface.
Within my application delegate's init: method, I initialize both a login and a fetch manager and get the following warnings for both:
warning: class 'MyAppDelegate' does not implement the 'HTTPManagerDelegate' protocol
warning: incompatible Objective-C types assigning 'struct HTTPManager *', expected 'struct LoginManager *'
Neither of the two classes being initialized are derived from HTTPManager, but they do implement the HTTPManagerDelegate protocol. The line of code that produces the above warning is:
_loginMgr = [[LoginManager alloc] initWithDelegate:self];
So what on earth is making LoginManager's initWithDelegate: method return an HTTPManager*? There is no inheritance and my return types are correct, so to me this is some dark form voodoo that I cannot best.
Here is the shell of my application. There are probably typos and small inconsistencies so ask me before assuming a syntactical problem:
// HTTPManager.h
#protocol HTTPManagerDelegate
...
#end
#interface HTTPManager : NSObject
{
id <HTTPManagerDelegate> _delegate;
...
}
- (HTTPManager *) initWithDelegate:(id <HTTPManagerDelegate>)delegate;
...
#end
// LoginManager.h
#protocol LoginManagerDelegate
...
#end
#interface LoginManager : NSObject <HTTPManagerDelegate>
{
id <LoginManagerDelegate> _delegate;
...
}
- (LoginManager *) initWithDelegate:(id <LoginManagerDelegate>)delegate;
...
#end
// MyAppDelegate.h
#interface MyAppDelegate : NSObject <NSApplicationDelegate, LoginManagerDelegate, FetchManagerDelegate>
{
LoginManager *_loginMgr;
...
}
...
#end
// MyAppDelegate.m
...
- (MyAppDelegate *) init
{
self = [super init];
if (self)
{
// WARNING HAPPENS HERE
_loginMgr = [[LoginManager alloc] initWithDelegate:self];
...
}
return self;
}
...
Thanks in advance.

The problem is that you have two methods with the same method signature -initWithDelegate: but with different types in their arguments and/or return types. The compiler cannot handle this case very well and in certain cases, it could also lead to errors at runtime (not in your case because the types in your methods do not differ in size, they're all pointers).
The reason for this (AFAIK) is that the runtime has no straightforward access to the types used in a method. It just reads a selector (which contains no type information) and decides based on this selector what method to call. To help the runtime pack the method arguments onto the stack, the compiler creates a table at compile time that maps selectors to the argument and return value types. This table has just one entry per selector. So if two methods exist that have the same selector but different types in arguments or return value, this system can fail.
In your case:
-init... methods should always return id and not a specific type.
This solves the problem of different return types. The other problem (different argument types) is harder to solve. You can either omit the protocol specification from your method declaration (initWithDelegate:(id)delegate) or give the two methods different names:
- (id) initWithHttpMgrDelegate:(id <HTTPManagerDelegate>)delegate;
- (id) initWithLoginMgrDelegate:(id <LoginManagerDelegate>)delegate;

Related

How to define a `Class` object type conforming to a protocol?

Consider the following Objective-C protocol declaration, which requires only class methods:
#protocol TDWMethoding<NSObject>
+ (void)foo;
+ (void)bar;
#end
Assuming I need to return an instance of a Class which conforms to this protocol from a method, how am I supposed to specify the return type?
- (nullable /*return-type*/)instantiateMethoding {
Class instance = ... // some implementation
if ([instance conformsToProtocol:#protocol(TDWMethoding)]) {
return instance;
}
return nil;
}
There are a number of working options I considered so far in regards to how to express the /*return-type*/, but each has its own downsides:
Class - this way it doesn't expose conformance. What kind of Class is it? What does it do? Does it conform to the protocol at all?
Class<TDWMethoding> - this looks like a viable solution and even was suggested a few times by other developers (here and here) but I personally find it inconsistent and misleading: when we have a variable of form Type<Protocol> *instance, it commonly means that protocol class methods should be sent to the instance's class ([[instance class] foo]) not the instance itself ([instance foo]);
id<TDWMethoding> and returning an instance of the class instead - this is consistent, but it requires me to instantiate the class, which is both redundant and prevents me from hiding the constructors of the utility classes which conforms to the protocol with NS_UNAVAILABLE macro.
Is there a better semantic to express such a return-type?
Class<TDWMethoding> is correct. It's not inconsistent. When something is of type Class, you send class methods to it. When something is an instance, and you want to send to the class, you access its -class.
That said, this does seem very strange, and likely means you're overusing Class methods. You should think hard about whether a sharedInstance is a better model for this.
But if you want to identify the type, Class<TDWMethoding> is correct, though id would likely be more common, as discussed in How to cast Class object to conformance witih protocol.
After digging a little deeper into The Objective-C Programming Language documentation, I actually found the exact answer to such a scenario:
Protocols can’t be used to type class objects. Only instances can be statically typed to a protocol, just as only instances can be statically typed to a class. (However, at runtime, both classes and instances respond to a conformsToProtocol: message.)
Which means that it's just not supported and I should implement this differently. (e.g. with use of a singleton pattern, as suggested in Rob's answer)
The solution is doesn't use such protocols at all. Why? Because it's inflexible.
It should be just:
#protocol TDWMethoding
- (void)foo;
- (void)bar;
#end
Then you will be able to do any what you want, for example you will be able to create wrapper for yours class, that will be implementing yours protocol.
#interface TDWMethodingModel<TDWMethoding>
#property (nonatomic, readonly) void (^fooCaller)(void);
#property (nonatomic, readonly) void (^barCaller)(void);
- (instancetype)initWithFooCaller:(void (^)(void))fooCaller barCaller:(void (^)(void))barCaller NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
#end
#implementation TDWMethodingModel
- (instancetype)initWithFooCaller:(void (^)(void))fooCaller barCaller:(void (^)(void))barCaller {
self = [super init];
if (nil == self) {
return nil;
}
_fooCaller = fooCaller;
_barCaller = barCaller;
return self;
}
- (void)foo {
self.fooCaller();
}
- (void)bar {
self.barCaller();
}
#end
then:
- (id<TDWMethoding>)instantiateMethoding
{
static id<TDWMethoding> methoding;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
methoding = [[TDWMethodingModel alloc] initWithFooCaller:^{
[SomeClass foo];
} barCaller:^{
[SomeClass bar];
}];
});
return methoding;
}

Pros and cons of using "id" as the return type of a custom "init" method, instead of a pointer to that class?

Assume the following Objective-C class:
#interface Appliance : NSObject
{
NSString *productName;
int voltage;
}
#end
What are the pros and cons of implementing init method A instead of B?
A) -(id)initWithName:(NSString *)name;
B) -(Appliance *)initWithName:(NSString *)name;
I see they both work in XCode, i.e. they both will result in a valid Appliance instance. "A" seems to be the standard among books I've read and codebases I've looked at, and I'm wondering why this is.
Point in fact, for quite some time the best practice return type from a class initializer (in Objective-C) is instancetype instead of id.
Oh, reopen. :-)
Indeed, you did not ask for the difference id vs. instancetype. And for -init… the answer to this non-asked Q would be easy: There is no difference, because the compiler converts id to instancetype silently.
You asked for id vs. CustomClass*. And you get a completely different answer from me: With CustomClass* a subclass had to cast the result of the superclass' designated initializer. Let's have an example:
#interface BaseClass : NSObject
- (BaseClass*)initWithWhatever; // Typed to class, designated initializer
#end
#implementation BaseClass
- (BaseClass*)initWithWhatever // Typed to class
{
self = [super init]; // What's the return type of -init (NSObject)?
…
}
#end
#interface Subclass : BaseClass
// First problem: I like it to announce in the interface, that a class overwrites
// a method of the base class. Doing so I would have to change the return type. Ugly.
// If I do not redeclare -initWithWhatever it is inherited from BaseClass, still
// having BaseClass* as the return type. Is that the truth? Really?
// However, I do not overwrite it here, but have a new initializer.
- (Subclass*)initWithSomethingElse;
#end
#implementation Subclass
- (Subclass*)initWithSomethingElse
{
// Second Problem:
// First, I have to execute the superclass' designated initializer
self = [super initWithWhatever];
// Wait a minute!
// self is a reference to Subclass. The return value of -initWithWhatever has the type
// BaseClass*. So I assign a reference of the base class to a reference of the subclass:
// Compiler error, false positive. The code is correct.
// So I would have to cast. Ugly, ugly, ugly.
#end
…
// Third problem:
Subclass *object = [[Subclass alloc] initWithWhatever];
// Typing -initWithWhatever to BaseClass* would lead to a compiler error here again.
// Compiler error, false positive. The code is correct.
To make the long story short: Without a mass of castings it would be impossible to type initializers to the concrete class.

Protocol or class specific selector in objective-c

Using a selector to call a method that exists in more that one class (but with different signatures on return or argument types) causes an Multiple methods named [method name] found... error.
This has been already settled in other questions:
Defeating the "multiple methods named 'xxx:' found" error
Issue with "Multiple methods named...."
Multiple methods named "count" found with mismatched result, parameter type or attributes
A related problem happens if the repeated method is in a protocol. Having a strongly typed protocol object is still ambiguous for the compiler since the object could also be an instance of other classes implementing the same-ish signature method:
#protocol ExistingMethodProtocol <NSObject>
// This method also exists in UIView, but with a different return type
- (NSString*)contentMode;
#end
#interface ImplementingClass : NSObject <ExistingMethodProtocol>
#end
#implementation ImplementingClass
- (NSString*)contentMode {return nil;}
- (void)problematicCall
{
// Multiple methods named... error
[self performSelector:#selector(contentMode)];
id<ExistingMethodProtocol> idOfProtocol = self;
// Multiple methods named... error too, even casted
[idOfProtocol performSelector:#selector(contentMode)];
}
#end
An alternative is to create the selector separately and then perform, thus bypasing the compiler check but causing a warning:
SEL selector = #selector(contentMode);
// Warning: PerformSelector may cause a leak because its selector is unknown
[object performSelector:selector];
What other alternatives could work here for checking and performing a method when a protocol has a method colliding with a same-ish signature?
my 2 cents. Use Runtime reference. In which case it bypasses the compiler warnings/error. Looks like there are several ways to do this, here is my solution.
#import <objc/message.h>
struct objc_method *method = class_getInstanceMethod([self class], #selector(contentMode));
id answer = method_invoke(self, method);
This should prevent errors from selectors in different protocols named the same. But I am a little unsure how this behaves with methods with different implementations in base and super classes.

What's the most robust and readable way of ensuring objects conform to a interface/protocol in Objective C?

I'm trying code to an interface (or a protocol in Objective C terminology), not an implementation.
It's critical that we check objects conform to protocol before calling methods on them to prevent crashes.
Three Ways
In compiler
At runtime
Both
Best Solution... Surely Number 1?
I thought the best way would be in the compiler:
Warnings ahoy if you screw up
Eliminates conformsToProtocol:/respondsToSelector: boilerplate
At runtime it's too late if you made a mistake - the best you can do is not execute the code/show an error
But I see a lot of code that's doing it at runtime. Why?
Is it a readability issue - needing id <Protocol> everywhere?
My Question
What's the most robust and readable way of ensuring objects conform to a interface/protocol?
Code
1. Checking In Compiler
#interface ReportController : NSObject {
id <ReportGenerator> generator;
id <ReportSender> sender;
id report;
}
#implementation ReportController
-(id)initWithReportGenerator:(id <ReportGenerator>)generator_
reportSender:(id <ReportSender>)sender_ {
// Usual init stuff
generator = generator_;
sender = sender_;
return self;
}
-(void)generateAndSend {
report = [generator generate];
[sender sendReport:report];
}
#end
2. Checking At Runtime
#interface ReportController : NSObject {
id generator;
id sender;
id report;
}
#implementation ReportController
-(id)initWithReportGenerator:(id)generator_
reportSender:(id)sender_ {
// Usual init stuff
generator = generator_;
sender = sender_;
return self;
}
-(void)generateAndSend {
if ([generator conformsToProtocol:#protocol(ReportGenerator)] &&
[sender conformsToProtocol:#protocol(ReportSender)]) {
report = [generator generate];
[sender sendReport:report];
} else {
[NSException raise:NSInternalInconsistencyException format:#"Objects didn't respond to protocols..."];
}
}
#end
You should use both. Consider e.g.:
#protocol Proto
- (void)someFunction;
#end
#interface C : NSObject
- (void)proto:(id<Proto>)p;
#end
// ...
NSString *s = #"moo";
id i = s;
C *c = [[C alloc] init];
[c proto:s]; // warns
[c proto:i]; // doesn't warn
Objective-C and Cocoa are too dynamic to generally check such things at compile time (NSProxy standins, classes dynamically adding methods and protocols, ...).
It is nice to catch as many of such errors at compile-time as possible, but that alone is not sufficient.
As long as you don't use plain id as the type, the compiler will at least warn you if you make a mistake at compile time. So you should be fine with your code example #1.
Of course, sometimes you might be forced to work with an id object that you get from a subsystem that is not under your control. In such cases you can cast the object back to the type you think it has (e.g. id <ReportGenerator>), but you are usually better off if you perform a runtime check first. Better be safe than sorry...
On a final note: If your protocol has optional parts (declared with the #optional keyword), then for those parts you will obviously be able to do runtime checks only. The #required keyword mentioned by apurv is necessary only if you want to be explicit in your protocol declaration (a protocol's parts are required by default), or if you mix optional and required parts.
You should create methods with #required type in protocol.
So whatever class wants to take a contract with this protocol, will must have to implement those methods.
It will definitely make sure that the required methods are available at compile time only.

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.