Creating an abstract class in Objective-C
Asked Answered
W

22

512

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?

Warble answered 23/6, 2009 at 18:42 Comment(4)
The answers below are great. I find this the issue of abstract classes is tangentially related to private methods — both are methods for restricting what client code can do, and neither exist in Objective-C. I think it helps to understand that the mentality of the language itself is fundamentally different from Java. See my answer to: stackoverflow.com/questions/1020070/#1020330Aldred
Thanks for the info on the mentality of the Objective-C community as opposed to other languages. That really does resolve a number of related questions I had (like why no straightforward mechanism for private methods, etc).Warble
so have a look at the CocoaDev site which gives it a java comparison cocoadev.com/index.pl?AbstractSuperClassHoe
Though Barry mentions it as an after thought (forgive me if I'm reading it wrong), I think you're looking for a Protocol in Objective C. See, for example, What is a Protocol?.Mouthpiece
B
635

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.

Boreas answered 23/6, 2009 at 18:56 Comment(5)
I think the most appropriate part of the answer was mentioning you could use @protocol instead to just define methods.Illiquid
To clarify: You can declare methods in a @protocol definition, but you cannot define the methods there.Gigantism
With a category method on NSException + (instancetype)exceptionForCallingAbstractMethod:(SEL)selector this works very nicely.Lion
This worked out for me since, IMHO, throwing an exception is more obvious to other developers that this is a desired behavior more so than doesNotRecognizeSelector.Brillatsavarin
Use protocols (for completely abstract class) or template method pattern where abstract class has partial implementation/ flow logic as given here #8146939. See my answer below.Nephelinite
B
265

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.

Bernhardt answered 23/6, 2009 at 18:47 Comment(5)
@Chuck, I did not downvote, but the NSObject reference suggests using this where you do NOT want to inherit a method, not to enforce overriding of a method. Although those may be the same thing, perhaps :)Rush
Why would you not want to just use a protocol in this instance? To me, this is nice to know for only method stubs, but not for a whole abstract class. The use case for this seems limited.Brutalize
I didn't downvote it, but the suggestion that you should cause an exception to be raised in the init method is the most likely reason for it. The most common format for a subclass will start it's own init method by calling self = [super init] - which will obediently throw an exception. This format works well for most methods, but I would never do it in anything where the subclass might call it's super implementation.Goshorn
You absolutely can create abstract classes in Objective-C, and it's quite common. There are a number of Apple framework classes that do this. Apple's abstract classes throw specific exceptions (NSInvalidArgumentException), often by calling NSInvalidAbstractInvocation(). Calling an abstract method is a programming error, which is why it throws an exception. Abstract factories are commonly implemented as class clusters.Denomination
@quellish: As you said: calling an abstract method is a programming error. It should be treated as such, instead of relying on runtime error reporting (NSException). This I think is the biggest issue for developers coming from other languages where abstract means "cannot instantiate an object of this type" in Obj-C it means "things will go wrong at runtime when you instantiate this class".Garry
R
60

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).

Rush answered 23/6, 2011 at 2:39 Comment(7)
Sure thing, @TomA, I hope it gives you ideas for other code that you can macro. My most-used macro is a simple reference to a singleton: the code says universe.thing but it expands to [Universe universe].thing. Big fun, saving thousands of letters of code...Rush
Great. Changed it a bit, though: #define mustOverride() @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] userInfo:nil].Mcmichael
@Yar: I don't think so. We use __PRETTY_FUNCTION__ all over the place, via a DLog(...) macro, as suggested here: https://mcmap.net/q/75141/-how-to-print-out-the-method-name-and-line-number-and-conditionally-disable-nslog.Mcmichael
Thanks, yeah, I have to stop with NSLog though I can type %@ %@ %@ faster than anyone now. But I do use the VTPG stuff occasionally. vgable.com/blog/2010/08/19/…Rush
for more details - #define setMustOverride() NSLog(@"%@ - method not implemented", NSStringFromClass([self class])); mustOverride()Sincerity
@Kirill this is already taken care of with the NSException throw. NSLog is another way to go, I guess...Rush
if u add base class and then inherit this class for example 10 times and forgot to implement this in one of classes u will get message with name of Base class not inherited one like Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[BaseDynamicUIViewController localizeUI] must be overridden in a subclass/category' In case i proposed u also get HomeViewController - method not implemented where HomeViewController inherited from Base - this will give more informationSincerity
S
42

The solution I came up with is:

  1. Create a protocol for everything you want in your "abstract" class
  2. 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.
  3. 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.

Silkstocking answered 21/6, 2012 at 19:3 Comment(7)
+1 This is really the solution that comes closest to an abstract Class in Java. I have used this approach myself and it works great. It is even allowed to name the protocol the same as the base class (just as Apple did with NSObject). If you then put the protocol and the base class declaration in the same header file it is almost indistinguishable from an abstract class.Heterosexuality
Ah, but my abstract class implements part of a protocol, the rest is implemented by subclasses.Marthena
you could have only the child classes implement the protocol and leave the superclass methods out all together instead of blank. then have properties of type Superclass <MyProtocol>. also, for added flexibility you can prefix your methods in your protocol with @optional.Fourthclass
This does not appear to work in Xcode 5.0.2; it only generates a warning for the "abstract" class. Not extending the "abstract" class generates the proper compiler warning, but obviously doesn't let you inherit the methods.Macfarlane
I prefer this solution but really don't like it, it really isn't a good code structure in project. // should use this as base type for subclasses. typedef BaseClass<BaseClassProtocol> BASECLASS; It's just a week rule, I don't like it.Mlawsky
If I understand this correctly, if a subclass omits the protocol implementation declaration entirely there will be no warning, which is what Itachi is talking about. I might try combining this with raising an exception. The advantage of this would be compile-time warnings for unimplemented methods so that no methods are left out.Erst
Because the base class implements the protocol the subclass shows no warning, in Xcode 9. Unless I’m misunderstanding step 2.Feign
C
35

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;
}
Capitation answered 23/6, 2009 at 18:45 Comment(5)
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...Aldred
The doesNotRecognizeSelector approach prevents Apple's suggested self=[super init] pattern.Devereux
@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.Said
I don't think this is a viable solution as subclasses may have perfectly legitimate calls to [super init].Reconstruct
@dlinsin: That's exactly what you want when the abstract class is not supposed to be initialised via init. Its subclasses presumably know what super method to call, but this stops careless invocation via "new" or "alloc/init".Sd
B
21

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.

Bisutun answered 23/6, 2009 at 18:57 Comment(3)
To me, this seems to be the appropriate way to go for cases where you would use abstract class, at least when it is meant to mean "interface" really (like in C++). Are there any hidden downsides to this approach?Pledge
@febeling, abstract classes -- at least in Java -- are not just interfaces. They also define some (or most) behavior. This approach could be good in some cases, though.Rush
I need a base class to implement certain functionality that my subclasses all share (removing duplication), but I also need a protocol for other methods that the baseclass should not handle (the abstract part). So I need to use both, and thats where it can get tricky to make sure your subclasses are implementing themselves properly.Gimble
N
19

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:

  1. Implement every abstract method in the base class.
  2. Make that implementation [self doesNotRecognizeSelector:_cmd];
  3. …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”.
  4. 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

  1. It get’s the job done efficiently, and somewhat conveniently.
  2. It’s fairly easy to understand. (Okay, that __builtin_unreachable() may surprise people, but it’s easy enough to understand, too.)
  3. 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?

Nigritude answered 23/7, 2013 at 18:20 Comment(1)
This is my new favourite solution - the __builtin_unreachable(); gem makes this work perfectly. The macro makes it self-documenting and the behaviour matches what happens if you call a missing method on an object.Lothar
A
12

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.

Azole answered 3/11, 2010 at 21:46 Comment(0)
I
7

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.

Immure answered 6/11, 2012 at 13:38 Comment(3)
I couldn't get it. I applied your suggestion on my base class -init method and now Xcode does not allow me create an instance of inherited class and a compile time error occurs unavailable.... Would you please explain more?Coruscate
Make sure you have an -init method in your subclass.Immure
It's the same as NS_UNAVAILABLE which will trigger an error every time you will try to call the method marked with such attribute. I don't see how it can be used on abstract class.Reeding
N
7

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?

Nephelinite answered 27/3, 2014 at 10:59 Comment(0)
S
6

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

Somatotype answered 8/12, 2013 at 15:13 Comment(2)
Would it be efficient to just return nil? Or would that cause an exception/other error to be thrown?Unapt
Well this is just to catch programmers for using the class directly, which i think makes for good use of an assert.Somatotype
S
5

(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.

example of the hint

Samal answered 3/5, 2012 at 19:55 Comment(0)
G
4

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
Garry answered 7/7, 2015 at 20:6 Comment(0)
E
3

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;
}
Enrollee answered 26/4, 2013 at 3:27 Comment(0)
S
3

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.

Sincerity answered 2/8, 2015 at 19:1 Comment(0)
T
2

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.

Torrid answered 29/10, 2014 at 18:18 Comment(0)
T
1

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.

Tubing answered 20/8, 2015 at 11:9 Comment(3)
But i am getting error when i call [super init] from derived class of that abstract class. How to solve that?Goidelic
@SahilDoshi I suppose that's the downside of using this method. I use it when I don't want to allow a class to be instantiated, & nothing inherits from that class.Tubing
yes, i understood that. but your solution will help for creating something like singleton class where we dont want anybody to call init. as per my knowledge in case of abstract class some class is going to inherit it. else whats the use of abstract class.Goidelic
S
0

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
Seventy answered 2/4, 2014 at 2:35 Comment(0)
C
0

Changing a little what @redfood suggested by applying @dotToString's comment, you actually have the solution adopted by Instagram's IGListKit.

  1. 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.
  2. 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.
  3. 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.

Corotto answered 18/10, 2016 at 17:24 Comment(0)
F
0

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
Fitzhugh answered 25/3, 2017 at 19:21 Comment(0)
C
0

Objective- C does not directly support Abstraction like Swift, however, anyObject is based on NSObject, we can simulate 90% behavior to do dependency injection.

This is my sample code.

#import <XCTest/XCTest.h>

@protocol CacheInterface <NSObject>
- (void)saveItem: (NSString*)item withKey:(NSString*)key;
- (NSString*)getItemForKey:(NSString*)key;
@end

//------------------------------------

@interface Cache : NSObject<CacheInterface>
- (instancetype)initWithMemoryCache: (NSObject<CacheInterface>*)memCache diskCache:(NSObject<CacheInterface>*) diskCache;
@end

@interface Cache()
@property(nonatomic) NSObject<CacheInterface>* memCache;
@property(nonatomic) NSObject<CacheInterface>* diskCache;
@end

@implementation Cache
- (instancetype)initWithMemoryCache: (NSObject<CacheInterface>*)memCache diskCache:(NSObject<CacheInterface>*) diskCache {
    self = [super init];
    self.memCache = memCache;
    self.diskCache = diskCache;
    return  self;
}

- (void)saveItem: (NSString*)item withKey:(NSString*)key {
    [self.memCache saveItem:item withKey:key];
    //save to disk cache
}

- (NSString *)getItemForKey:(NSString *)key {
    return  [self.memCache getItemForKey:key];
    //fallback to disk cache if can't get from memcache
}

@end

//---------------------------------

@interface MockCache : NSObject<CacheInterface>
@end

@interface MockCache()
@property(nonatomic)NSMutableDictionary*dict;
@end

@implementation MockCache
- (instancetype)init {
    self = [super init];
    self.dict = [[NSMutableDictionary alloc] init];
    return  self;
}
- (void)saveItem:(NSString *)item withKey:(NSString *)key {
    self.dict[key] = item;
}
- (NSString *)getItemForKey:(NSString *)key {
    return self.dict[key];
}
@end

//--------------------------------

@interface SampleTest : XCTestCase

@end

@implementation SampleTest

- (void)testCache {
    Cache *sut = [self makeSUT];
    NSString *item = @"ABC";
    NSString *key = @"key";
    [sut saveItem: item withKey:key];
    XCTAssertEqual(item, [sut getItemForKey:key]);
}

- (Cache*)makeSUT {
    MockCache *mockMemCache = [[MockCache alloc] init];
    Cache *sut = [[Cache alloc] initWithMemoryCache:mockMemCache diskCache:nil];
    return sut;
}
@end

Czarism answered 12/5, 2023 at 7:14 Comment(1)
Where's the abstract class here? All you have is two classes that conform to a protocol. Both classes can be used as-is. I'm not sure you understood the question. And Swift doesn't support abstract classes either.Pleader
R
-3

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.

Raine answered 22/5, 2014 at 14:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.