Understanding Class in ObjectC - objective-c

in objc.h , there is definition for Class
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
Case : use Class in NSObject :
/*************** Basic protocols ***************/
#protocol NSObject
- (BOOL)isEqual:(id)object;
- (NSUInteger)hash;
- (Class)superclass;
- (Class)class;
- (id)self;
Hard to understand, so Class is just structure, not real class like NSObject etc.
What is the real purpose of Class ?

All of the dynamic behaviors of the Objective-C runtime are available because of the Class class. It's not a class that you will ever subclass or implement. The runtime fills in metadata about your class that can be accessed for introspection or modification.
Languages such as C++ and even Java have very limited support for this sort of thing. Objective-C is closer to the Ruby or Python scripting languages in this regard. You can actually replace instance methods in existing classes with your own implementation at run-time and affect the class in other ways that most compiled languages just can't touch.

I think you're on the wrong way.
the header file should loook like this:
#import <Foundation/NSObject.h>
#interface Fraction: NSObject {
int numerator;
}
-(void) print;
#end
And the implementation (.m file) like this
#import "Fraction.h"
#import <stdio.h>
#implementation Fraction
-(void) print {
printf( "%i", numerator );
}
#end
source
regards

In Objective-C, classes are "first-class objects". They are essential in runtime type checking, e.g. to check if an object is a string you can use
[obj isKindOfClass:[NSString class]];
-isKindOfClass: needs to accept an Objective-C class as a parameter, and Class is a representation of it.
(You seldom need to care the type definitions in objc.h unless you need to manipulate the Objective-C runtime below the C API level. )

Class lets the Objective-C runtime system know where to look for method tables (and instance variables etc.). In particular, when you write
[self foo: bar];
the runtime system calls
objc_msgSend(self, #selector(foo:), bar);
and then it uses self's type to find the right Class to find the appropriate method table to find the implementation corresponding to the foo: message. And then run it.

Related

Is it possible to create warnings for methods that must be overridden? [duplicate]

This question already has answers here:
Implement a pure virtual method in Objective-C
(6 answers)
Closed 9 years ago.
I was reading Creating an abstract class in Objective-C, and I wasn't terribly satisfied with the fact that the "abstractness" of the class is only enforced at runtime. I'd like to be able to show some warnings if the method is not implemented in a subclass. Ideally, this could be condensed down to one or two #defines.
Is there a clever use of __attribute((available,deprecated,etc))__ or a #warning with some careful #pragma clang diagnostic pushes that can accomplish this?
I think this is possible; I just don't know enough about Clang to figure it out.
EDIT:
There's no need to tell me I should be using protocols. I already use them for this purpose. I'm more curious to see if it can be done (to learn more about Clang) than whether it should be done.
I see this working the in a similar way to NSManagedObject requiring properties to be marked #synthesized or #dynamic. I've researched this, and I see that in NSManagedObject.h the class is marked NS_REQUIRES_PROPERTY_DEFINITIONS, which translates to __attribute__((objc_requires_property_definitions)) in NSObjCRuntime.h. Is there some creative use of these built-in #defines that could make this work?
EDIT #2:
For people saying that abstract superclasses are not the Objective-C way, I'll direct you to the documentation for UIMotionEffects:
Subclassing Notes
This class is abstract and cannot be instantiated
directly.
I prefer the NSException approach (which is a run-time, not a compile time, error).
In your superclass:
#interface NSSuperclass : NSObject
- (void)execute;
#end
#implementation NSSuperclass
- (void)execute
{
#throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:#"Called %# on superclass NSSuperclass, this should only be called on subclasses", NSStringFromSelector(_cmd)]
userInfo:#{#"object": self}];
}
#end
And then override this method in your subclasses.
I go for protocol
untested code, the idea is use protocol type (maybe combined with class type) instead of just class type.
#interface BaseClass : NSObject
- (void)foo;
#end
#protocol BaseClassProtocol : NSObject
#required
- (void)bar;
#end
#interface SubClass : BaseClass <BaseClassProtocol>
#end
#interface SubClass2 : BaseClass // no <BaseClassProtocol>
#end
// some code
BaseClass <BaseClassProtocol> * obj = [SubClass new]; // good
BaseClass <BaseClassProtocol> * obj = [SubClass2 new]; // warning

Accessing static variables that are simulating class variables from unit tests

Is there an Objective-C runtime library function (unlikely) or set of functions capable of inspecting static (quasi-class level) variables in Objective-C? I know I can utilize a class accessor method but I'd like to be able to test without writing my code "for the test framework".
Or, is there a obscure plain C technique for external access to static vars? Note this information is for unit testing purposes—it needn't be suitable for production use. I'm conscious that this'd go against the intent of static vars... a colleague broached this topic and I'm always interested in digging into ObjC/C internals.
#interface Foo : NSObject
+ (void)doSomething;
#end
#implementation Foo
static BOOL bar;
+ (void)doSomething
{
//do something with bar
}
#end
Given the above can I use the runtime library or other C interface to inspect bar? Static variables are a C construct, perhaps there's specific zone of memory for static vars? I'm interested in other constructs that may simulate class variables in ObjC and can be tested as well.
No, not really, unless you are exposing that static variable via some class method or other. You could provide a + (BOOL)validateBar method which does whatever checking you require and then call that from your test framework.
Also that isn't an Objective-C variable, but rather a C variable, so I doubt there is anything in the Objective-C Runtime that can help.
The short answer is that accessing a static variable from another file isn't possible. This is exactly the same problem as trying to refer to a function-local variable from somewhere else; the name just isn't available. In C, there are three stages of "visibility" for objects*, which is referred to as "linkage": external (global), internal (restricted to a single "translation unit" -- loosely, a single file), and "no" (function-local). When you declare the variable as static, it's given internal linkage; no other file can access it by name. You have to make an accessor function of some kind to expose it.
The extended answer is that, since there is some ObjC runtime library trickery that we can do anyways to simulate class-level variables, we can make make somewhat generalized test-only code that you can conditionally compile. It's not particularly straightforward, though.
Before we even start, I will note that this still requires an individualized implementation of one method; there's no way around that because of the restrictions of linkage.
Step one, declare methods, one for set up and then a set for valueForKey:-like access:
// ClassVariablesExposer.h
#if UNIT_TESTING
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#define ASSOC_OBJ_BY_NAME(v) objc_setAssociatedObject(self, #v, v, OBJC_ASSOCIATION_ASSIGN)
// Store POD types by wrapping their address; then the getter can access the
// up-to-date value.
#define ASSOC_BOOL_BY_NAME(b) NSValue * val = [NSValue valueWithPointer:&b];\
objc_setAssociatedObject(self, #b, val, OBJC_ASSOCIATION_RETAIN)
#interface NSObject (ClassVariablesExposer)
+ (void)associateClassVariablesByName;
+ (id)classValueForName:(char *)name;
+ (BOOL)classBOOLForName:(char *)name;
#end
#endif /* UNIT_TESTING */
These methods semantically are more like a protocol than a category. The first method has to be overridden in every subclass because the variables you want to associate will of course be different, and because of the linkage problem. The actual call to objc_setAssociatedObject() where you refer to the variable must be in the file where the variable is declared.
Putting this method into a protocol, however, would require an extra header for your class, because although the implementation of the protocol method has to go in the main implementation file, ARC and your unit tests need to see the declaration that your class conforms to the protocol. Cumbersome. You can of course make this NSObject category conform to the protocol, but then you need a stub anyways to avoid an "incomplete implementation" warning. I did each of these things while developing this solution, and decided they were unnecessary.
The second set, the accessors, work very well as category methods because they just look like this:
// ClassVariablesExposer.m
#import "ClassVariablesExposer.h"
#if UNIT_TESTING
#implementation NSObject (ClassVariablesExposer)
+ (void)associateClassVariablesByName
{
// Stub to prevent warning about incomplete implementation.
}
+ (id)classValueForName:(char *)name
{
return objc_getAssociatedObject(self, name);
}
+ (BOOL)classBOOLForName:(char *)name
{
NSValue * v = [self classValueForName:name];
BOOL * vp = [v pointerValue];
return *vp;
}
#end
#endif /* UNIT_TESTING */
Completely general, though their successful use does depend on your employment of the macros from above.
Next, define your class, overriding that set up method to capture your class variables:
// Milliner.h
#import <Foundation/Foundation.h>
#interface Milliner : NSObject
// Just for demonstration that the BOOL storage works.
+ (void)flipWaterproof;
#end
// Milliner.m
#import "Milliner.h"
#if UNIT_TESTING
#import "ClassVariablesExposer.h"
#endif /* UNIT_TESTING */
#implementation Milliner
static NSString * featherType;
static BOOL waterproof;
+(void)initialize
{
featherType = #"chicken hawk";
waterproof = YES;
}
// Just for demonstration that the BOOL storage works.
+ (void)flipWaterproof
{
waterproof = !waterproof;
}
#if UNIT_TESTING
+ (void)associateClassVariablesByName
{
ASSOC_OBJ_BY_NAME(featherType);
ASSOC_BOOL_BY_NAME(waterproof);
}
#endif /* UNIT_TESTING */
#end
Make sure that your unit test file imports the header for the category. A simple demonstration of this functionality:
#import <Foundation/Foundation.h>
#import "Milliner.h"
#import "ClassVariablesExposer.h"
#define BOOLToNSString(b) (b) ? #"YES" : #"NO"
int main(int argc, const char * argv[])
{
#autoreleasepool {
[Milliner associateClassVariablesByName];
NSString * actualFeatherType = [Milliner classValueForName:"featherType"];
NSLog(#"Assert [[Milliner featherType] isEqualToString:#\"chicken hawk\"]: %#", BOOLToNSString([actualFeatherType isEqualToString:#"chicken hawk"]));
// Since we got a pointer to the BOOL, this does track its value.
NSLog(#"%#", BOOLToNSString([Milliner classBOOLForName:"waterproof"]));
[Milliner flipWaterproof];
NSLog(#"%#", BOOLToNSString([Milliner classBOOLForName:"waterproof"]));
}
return 0;
}
I've put the project up on GitHub: https://github.com/woolsweater/ExposingClassVariablesForTesting
One further caveat is that each POD type you want to be able to access will require its own method: classIntForName:, classCharForName:, etc.
Although this works and I always enjoy monkeying around with ObjC, I think it may simply be too clever by half; if you've only got one or two of these class variables, the simplest proposition is just to conditionally compile accessors for them (make an Xcode code snippet). My code here will probably only save you time and effort if you've got lots of variables in one class.
Still, maybe you can get some use out of it. I hope it was a fun read, at least.
*Meaning just "thing that is known to the linker" -- function, variable, structure, etc. -- not in the ObjC or C++ senses.

Does Objective-C have something like C++ virtual functions?

In objective-c it is possible to add a #dynamic to a property.
Is this also possible for normal instance methods?
EDIT
I think i wasn't clear enough.
I want to do the following:
#interface MyClass
#property (retain) NSObject *somePropertyObject;
- (void) myMethod;
#end
#implementation MyClass
#dynamic somePropertyObject;
//Make myMethod dynamic. I do not want to implement it. Like C++ Virtual
#end
If you mean "How can I declare a method, but not provide a definition which I will subsequently provide at runtime?" Then it's easy, just use a category. Like this:
#interface MyObject : NSObject
// Methods I'll define
- (void)doFoo;
#end
#interface MyObject (DynamicallyProvidedMethods)
// Methods I won't
- (void)myDynamicMethod;
#end
#implementation MyObject
// Methods I'll define
- (void)doFoo
{
}
#end
The compiler will not complain, however if you call -myDynamicMethod at runtime, unless you have provided an implementation for it somehow, it will crash with "unrecognized selector." You can, of course, test for that at runtime by calling respondsToSelector:.
Relatedly, if you're looking to do a near-equivalent of a base class pure virtual method, I would recommend providing an empty implementation that asserts when called if it has not been overridden by a subclass. You can do that like so:
NSAssert((class_getInstanceMethod([self class], _cmd) == class_getInstanceMethod([MyObject class], _cmd)),
#"Subclass of %# must override -%#",
NSStringFromClass([MyObject class]),
NSStringFromSelector(_cmd));
// ...where overridesSelector:ofBaseClass: looks like:
//
// return ;
Of course, that won't alert you to problems at compile time, but it's better than nothing.
HTH
I think you might be asking how to declare a method that will be implemented some time later somewhere else.
The Objective-C way to do that is to use Protocols.
You declare a protocol like this, usually in a header file
#protocol MyProtocol <NSObject> {
#optional
- (void)optionalMethod;
#required
- (void)requiredMethod;
}
#end
This declares two methods, one which is optional and one is required. To use this protocol you declare the conformance when declaring the class that will implement the protocol
#interface MyConformingClass : NSObject <MyProtocol> {
}
// you don't have to redeclare methods that are declared in the protocol
#end
This new class is checked at compile time for the implementation of requiredMethod so it has to implement it, but it can choose whether or not to implement the optionalMethod
Now, any class that requires instances of objects to conform to the protocol can declare this, for example, in the interface
#interface RequiringClass : NSObject {
MyConformingClass <MyProtocol> *conformingClassObject;
}
…
#end
Again, this is checked at compile time
To make sure that the conforming class implement the #optional methods, we can use this handy structure
if [conformingClassObject respondsToSelector:#selector(optionalMethod)] {
[conformingClassObject optionalMethod];
} else {
// Do something here because the optional method isn't provided
}
Examples of this are all over Cocoa - it's a class can provide a list of actions that it would like to farm out to it's delegate, the delegate adopts the protocol and provides the implementations of those delegate methods. The calling object can then check if this delegate responds to those methods at runtime as I've described above, and call those methods to perform actions, or provide information where ever it needs to.
This is used quite a lot in Objective-C, where classes provide a list of methods that they would like some other class to perform, unlike virtual functions, where a class declares functions it wants subclasses to provide implementations for. Particularly as Composition is favoured over inheritance in the language. Rather than create a subclass to provide an implementation, you just create another class that can do the same thing, and add a reference to that in the class instead.
No.
#dynamic is just an instruction to the compiler that says: "Don't bother generating accessors for this property, I'm going to provide my own."
Using #dynamic with other methods wouldn't be helpful because the compiler doesn't generate any methods other than accessors for you, and of course you're supplying the other methods anyway.
What are you trying to accomplish?

Construction "Class<? extends SomeType>" variable declaration in Objective-C

I am just curious about whether declaring a variable in a way known from Java is possible in Objective-C:
Class<?extends SomeType>
For example: I have a class called MyClass. It has a static method
+ (void)myMethod
It has also two subclasses: MySubclassA and MySubclassB. I have such code:
Class myClass;
if(<some condition>) {
myClass = [MySubclassA class];
} else {
myClass = [MySubclassB class];
}
[myClass myMethod];
This code works fine, there are no compiler warnings, but I am just curious whether the construction I mentioned is somehow present in Objective-C.
Thanks!
Objective-C does not have templates (like C++) or generic types with type erasure (like Java) or runtime generic types (like C#). Unlike these languages, Objective-C messages are dynamically dispatched at runtime (instead of bound at compile time). Thus, many of the systems for producing type-agnostic code in C++, Java or C# are unnecessary. Objective-C prefers "duck-typing" whereby any object that responds to a given selector (message) can be given that message by calling code, regardless of the receiving object's type. Since classes are objects in Objective-C, the same is true for class methods as for instance methods.
So, given
#interface MyClassA : NSObject
{}
- (void)someMethod;
#end
#interface MyClassB: NSObject
{}
- (void)someMethod;
#end
calling code can look like this
- (void)someOtherMethodInAnOtherClassWithObject:(id)obj
{
[obj someMethod];
}
This code will compile and will work fine at runtime, assuming obj is either an instance of MyClassA or MyClassB.
Of course, good practice would dictate that you define a #protocol in this situation:
#protocol MyProtocol
- (void)myMethod
#end
and declare that your MyClassA and MyClassB both implement the MyProtocol protocol. Your calling code would then look like
- (void)someOtherMethodInAnOtherClassWithObject:(id<MyProtocol>)obj
{
[obj someMethod];
}
and the compiler would give you a warning/error (depending on -W flags) if you tried to call someOtherMethodInAnOtherClassWithObject:, passing an object of a type that doesn't implement the MyProtocol interface.
Note that id<MyProtocol> is not a generic type, it's an instance of type id that you are claiming implements the MyProtocol protocol. Also note that the first version of client code works just fine because all that really maters is whether obj can respond to the -myMethod selector.

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.