I have been reading about Protocols on Objective-C but I cannot grasp this:
Consider this line
Person <CoordinateSupport> *person = [[Person alloc] init];
What is the purpose of declaring the variable to conform to the protocol CoordinateSupport? Is this something just for compile time, so Xcode can warn me if I assign something different to person or is there any purpose at run time?
I cannot see how a variable can conform to a protocol. OK, a class is easy to see, because you can have a protocol defining methods that you want some class to follow but an ivar?
I am not seeing it.
The standard pattern when declaring that a variable conforms to a protocol is to give it the "any object" type, id. Declaring that a variable both has a specific type and conforms to a protocol is typically redundant – I'll explain why later. For now, let's talk about variables of type id<P>, where P is some protocol, and why they're useful. This type should be read as "an instance of any class that conforms to P."
To concretize the discussion that follows, let's define a protocol:
#protocol Adder
- (NSInteger)add:(NSInteger)a to:(NSInteger)b;
#end
I cannot see how a variable can conform to a protocol.
This one is easy. A variable conforms to an Objective-C protocol when it represents an instance of a class that implements all of the required methods in the protocol.
#interface Abacus : NSObject <Adder>
#end
#implementation Abacus
- (NSInteger)add:(NSInteger)a to:(NSInteger)b { return a + b; }
- (NSInteger)beadCount { return 91; }
#end
Given this Abacus class, you could, of course, create a new Abacus:
Abacus *a = [[Abacus alloc] init];
NSLog(#"%ld", (long)[a add:5 to:6]); // 11
NSLog(#"%ld", (long)[a beadCount]); // 91
But you could also declare a to just be of type id<Adder. Remember, that means the type of a is "an instance of any class that conforms to Adder."
id<Adder> a = [[Abacus alloc] init];
NSLog(#"%ld", (long)[a add:5 to:6]); // 11
NSLog(#"%ld", (long)[a beadCount]); // Compile error: No known instance method for selector 'beadCount'
The compiler complains because all we said about the type of a is that it is a class that conforms to Adder, and nowhere in the Adder protocol do we say anything about a method named beadCount.
What is the purpose of declaring the variable to conform to [a protocol]?
The purpose is for information hiding. When you want a class that conforms to Adder, you don't need to care about what the actual class is – you just get an id<Adder>. Imagine that Abacus is a system class, and you've written the following code:
- (Abacus *)getAdder { return [[Abacus alloc] init]; }
- (void)doWork {
Abacus *a = [self getAdder];
// Do lots of adding...
}
Then, in iOS 42, Apple comes up with a new innovation – the Calculator class! Your friends tell you that Calculator adds two numbers together more than twice as fast as Abacus, and all the cool kids are using it! You decide to refactor your code, but you realize that not only do you have to change the return type of getAdder, but also the types of all the variables to which you assign the return value of getAdder! Lame. What if you had done this instead:
- (id<Adder>)getAdder { return [[Abacus alloc] init]; }
- (void)doWork {
id<Adder> *a = [self getAdder];
// Do lots of adding...
}
Now, when you want to migrate to Calculator, you just need to change the body of getAdder to return [[Calculator alloc] init] and you're done! One line. The rest of your code stays exactly the same. In that case, you have hidden the true type of the instance returned from getAdder from the rest of your code. Information hiding makes refactoring easier.
Lastly, I promised to explain why something like Abacus <Adder> *a = ... is usually redundant. What you're saying here is "a is an instance of Abacus that conforms to Adder." But you (and the compiler) already know that Abacus conforms to Adder – it's right there in the interface declaration! As rmaddy points out, there are some cases where you want to talk about an instance that is either a given class, or a subclass thereof, and also specify that it conforms to a protocol, but those situations are rare, and most often specifying both a class and protocol conformance is unneeded.
For more information, check out Apple's Working with Protcols guide.
Related
Does Objective-C have an equivalent to java annotations?
What's I'm trying to do is create a property and be able to somehow access some metadata about it.
I want to be able to determine what type of classes should go in my array so I'd like to annotate it somehow to say so. Then later be able to access that annotation via something like the runtime library where I can access lists of properties and their names.
//Put some sort of annotation giving a class name.
#property (strong) NSArray *myArray;
You said:
I want to be able to determine what type of classes should go in my array so I'd like to annotate it somehow to say so. Then later be able to access that annotation via something like the runtime library where I can access lists of properties and their names.
There are a few ways to do this sort of thing in Objective-C. Apple's frameworks do this sort of thing by adding a class method that returns the required information. Examples: dependent keys in KVO, +[CALayer needsDisplayForKey:] and related methods.
So, let's create a class method that returns an array of classes that can go into your container property, given the property name. First, we'll add a category to NSObject to implement a generic version of the method:
#interface NSObject (allowedClassesForContainerProperty)
+ (NSArray *)allowedClassesForContainerPropertyWithName:(NSString *)name;
#end
#implementation NSObject (allowedClassesForContainerProperty)
+ (NSArray *)allowedClassesForContainerPropertyWithName:(NSString *)name {
if (class_getProperty(self, name.UTF8String)) {
return #[ [NSObject class] ];
} else {
[NSException raise:NSInvalidArgumentException
format:#"%s called for non-existent property %#", __func__, name];
abort();
}
}
#end
As you can see, this default version of the method doesn't do anything particularly useful. But adding it to NSObject means we can send the message to any class without worrying about whether that class implements the method.
To make the message return something useful, we override it in our own classes. For example:
#implementation MyViewController
+ (NSArray *)allowedClassesForContainerPropertyWithName:(NSString *)name {
if ([name isEqualToString:#"myArray"]) {
return #[ [UIButton class], [UIImageView class] ];
} else {
return [super allowedClassesForContainerPropertyWithName:name];
}
}
...
We can use it like this:
SomeViewController *vc = ...;
SomeObject *object = ...;
if ([[vc.class allowedClassesForContainerPropertyWithName:#"bucket"] containsObject:object.class]) {
[vc.bucket addObject:object];
} else {
// oops, not supposed to put object in vc.bucket
}
There is no native support of this functionality, but you may to take a look at following solution — https://github.com/epam/lib-obj-c-attr/ It is compile time implementation of attributes. Definition of attributes based on defines but not on comments as in other solutions like ObjectiveCAnnotate.
Objective C does not support generics like in Java but ofcourse the language is very flexible that you can accomplish almost anything with simple tricks and knowledge. To implement a generic like feature you could create a category on NSArray class and create your own method to initialize the array and then check to see if the object is really the type of the object you want.
I would write a simple category on NSArray to have such functionality. Say suppose, I want my array to hold objects of class MyClass only then my category would look like,
#interface NSArray(MyCategory)
#end
#implementation NSArray(MyCategory)
-(NSArray*)arrayWithMyClasses:(NSArray*)classes{
if([classes count] > 0){
NSMutableArray *array = [[NSMutableArray alloc] init];
for(id anObj in classes){
NSAssert([anObj isKindOfClass:[MyClass class]], #"My array supports only objetcts of type MyClass");
[array addObject:anObj];
}
return array;
}
return nil;
}
#end
Of course, there is some limitations to it. Since you have created your own category, you should use your own method to initialize and create your own array.
No, Objective-C has no annotation or generics support.
A way to implement such a thing would be to hack Clang to read comments and associate a metadata object to the original object. But, you would be tied to your hacked compiler.
NSString *v1 = [[NSString alloc] init];
// associate
static char key;
NSString *v2 = [[NSString alloc] init];
objc_setAssociatedObject (
v1,
&key,
v2,
OBJC_ASSOCIATION_RETAIN
);
// retrieve
NSString *associate = (NSString *)objc_getAssociatedObject(v1, &key);
Qualifying with a protocol wouldn't be much trouble, and you could test if the collection implements it, but along the way you would need to create a category for each type on the same collection. This would require a different collection at compile time using macros. Overly complicated.
#interface Tomato:NSObject #end
#implementation Tomato #end
#protocol TomatoNSArray <NSObject>
- (Tomato*)objectAtIndexedSubscript:(NSUInteger)index;
- (void)setObject:(Tomato*)tomato atIndexedSubscript:(NSUInteger)index;
#end
// here is the problem, you would need to create one of this for each type
#interface NSMutableArray (TomatoNSArray) <TomatoNSArray>
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
NSMutableArray<TomatoNSArray> *tomatoes = [[NSMutableArray alloc] initWithCapacity:2];
tomatoes[0] = [Tomato new];
tomatoes[1] = [NSObject new]; // warning: incompatible pointer types
}
}
Does Objective-C have an equivalent to java annotations?
Not exactly an equivalent, but there is, and it's better. In Objective-C, the compiler has to store some type and name information in the compiled code (because the language is highly dynamic, a lot of things happen at runtime as opposed to compile time), for example method names ("selectors"), method type signatures, data about properties, protocols, etc. The Objective-C runtime library then has access to this data. For example, you can get the list of properties an object has by writing
id object = // obtain an object somehow
unsigned count;
objc_property_t *props = class_copyPropertyList([object class], &count);
Or you can check what class an object belongs to:
if ([object isKindOfClass:[NSArray class]]) {
// do stuff
}
(Yes, part of the runtime library is itself wrapped into some methods of NSObject for convenience, others only have C function APIs.)
If you specifically want to store custom metadata about an object or a class, you can do that using associated references.
I expect it should be clear now, the answer is NO, not at the moment.
Some people found some alternatives which seem to work in their specific use cases.
But in general there is no comparable feature yet in objective-c. IMHO clang metadata seems to provide a good foundations for this, but as long as there is not support from Apple this will not help, as far as i understood it.
Btw. I guess it should be clear, but just to repeat for all: two changes are required to support annotations as provided in java.
The language need an extension the annotate e.g. methodes, properites, classes, ... in the source code.
A standard interface is required to access the annotated information. This can only provide by apple.
Most alternativ soltuions move the annotation information into runtime and define their own interface. The objective-c runtime provide a standard interface but only with some trick you can annotate properties and still the isse of runtime population.
The typical use case for suche a feature is an IOC container (in Java e.g. Spring) which use the annotated information to inject other objects.
I would suggest to open an feature requrest for Apple to support this.
The answer to your question is that Objective-C does not have a direct equivalent of annotations as found in Java/C#, and though as some have suggested you might be able to engineer something along the same lines it probably is either far too much work or won't pass muster.
To address your particular need see this answer which shows how to construct an array which holds objects of only one type; enforcement is dynamic and not static as with parametric types/generics, but that is what you'd be getting with your annotation so it probably matches your particular need in this case. HTH.
What you need maybe a metadata parser for Objective-C. I have used ObjectiveCAnnotate (compile time retrievable) and ROAnnotation(runtime retrievable).
Given this:
Person.h:
#interface Person
{
}
- (void) sayHello;
#end
Person.m:
#import "Person.h"
#implementation Person
- (void)sayHello
{
printf("%s", "Steve");
}
#end
How do you instantiate the Person? I tried this:
Person *p = [Person new];
That doesn't work, nor this:
Person *p = [Person alloc];
[UPDATE]
I forgot to tell, I already tried inheriting from NSObject, the new and alloc works. I'm just curious if we can instantiate a class that doesn't inherit from NSObject?
You absolutely can do so. Your class simply needs to implement +alloc itself, the way that NSObject does. At base, this just means using malloc() to grab a chunk of memory big enough to fit the structure defining an instance of your class.
Reference-counted memory management would also be nice (retain/release); this is actually part of the NSObject protocol. You can adopt the protocol and implement these methods too.
For reference, you can look at the Object class, which is a root ObjC class like NSObject, that Apple provides in its open source repository for the Objective-C runtime:
#implementation Object
// Snip...
+ alloc
{
return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());
}
// ...
- init
{
return self;
}
// And so on...
That being said, you should think of NSObject as a integral part of the ObjC runtime. There's little if any reason to implement your own root class outside of curiosity, investigation, or experimentation (which should, however, not be discouraged at all).
You must:
Inherit from NSObject,
Do a "poor man's" class with your own mallocs, etc, or
Use Objective-C++ and create a C++ class.
Of course, neither of the other two fit into Objective-C storage management, and their call protocols, etc, are different.
There is (very likely) no good reason to not want to inherit from NSObject, but there are many good reasons to do so.
I would be curious as to your reason for why you don't want to inherit from NSObject. I would guess it stems from a lack of knowledge rather than a real need.
But even without knowing that reason: Don't do it. It's so hard to do this well in a way that it still plays nice with other Objective-C classes as to be virtually impossible.
Anyway, you're instantiating your objects in a way that hides what's really done. While in Java, you usually create instances via the default constructor method new, in Objective-C you instantiate by calling alloc on the class and then init on the instance:
Person *aPerson = [[Person alloc] init];
(It is possible to just use Person new, but I wouldn't do it because it hides what's really done from you)
You implement your class such that you inherit from NSObject and then, if necessary, write your own init method.
If you want to log to the console, use NSLog:
NSLog(#"Hello %#", #"Steven");
(#"" is a special constructor for a NSString. Strings in Objective-C are not byte arrays, but objects.)
you can't..
Alloc and new ..copy init all these methods are defined in NSObject..
You cannot also create your own since apple does not provide NSObject implementation class..so you have to inherit from NSObject or its subclass so that you can initialize your class
I am very, very new to Obj-C, and will have a ton of questions. (I have the book "iPhone Programming, The Big Nerd Ranch Guide", but it doesn't address the differences between C# and Obj-C. Does anyone know of a doc that does address the differences?).
Anyway, my question is above...
In Objective-C, object allocation and initialization are separate operations, but it's common and a good practice to see them called in the context of the same expression:
MyClass *myInstance = [[MyClass alloc] init];
// ...
[myInstance release];
In C#, allocation and initialization happen when you use new:
MyClass myInstance = new MyClass();
The runtime allocates the instance and then calls the constructor.
So yes, the C# constructor is equivalent to the Objective-C initializer, but the usage is different.
Apart from this ... init in Objective-C is just a normal instance method, without any special semantics. You can call it at any point. In C#, constructors are very special static-like methods treated differently by the runtime and with special rules. For example, the C# compiler enforces calls to the base class constructor.
They are similar only as much as you can compare two completely different methods for creating an object. Checkout this information on the Objective-C Runtime.
The following is a very simple (but hopefully not misleading) explanation:
Objective-C
id object = [MyObject alloc]; // allocates the memory and returns a pointer. Factory-like method from NSObject (unless your class overrides it)
MyObject *myObj = [object init]; // initializes the object by calling `-(id)init`. You'll want to override this, or a similar init method for all your classes.
Usually written like this:
MyObject *myObj = [[MyObject alloc] init];
From what I know, the C# constructor allocates the memory and calls the appropriate constructor function to initialize the object.
A difference is that in C# you can't call an inherited constructor (see the bottom of the link above) but in Obj-C this will compile, but will give you wrong results.
#interface ClassA : NSObject
- (id) initWithInteger:(int)num;
#end
#interface ClassB : ClassA
- (id) init;
#end
#implementation ClassB
- (id) init
{
self = [supere initWithInteger:10];
return self;
}
// main
ClassA *a = [[ClassA alloc] initWithInteger:10]; //valid
ClassB *a = [[ClassB alloc] initWithInteger:10]; // will call init from classA, bypassing and not calling init for classB.
Just be careful with weak/dynamic typed language of Objective-C
They're similar, but not identical. Technically, a constructor fully creates and initializes an instance, while an initializer takes an already constructed instance (usually gotten through alloc) and sets the instance up so that it's ready to be used.
As for the differences between Objective-C and C#: They're two different and mostly unrelated languages. When you're learning a new language, trying to think of it as "Like this language I already know, but with these differences" can actually make it harder to learn, because there are a lot of differences and they're often subtle, so going in with assumptions from another language will confuse you. If you search around Stack Overflow, you'll find a lot of PHP programmers who start to learn a new language and immediately wonder "How do I do variable variables in this language?" It's like looking for a list of the differences between English and Chinese — you're better off not trying to treat one like the other. Keep in mind what you already know, but try not to assume any of it is the same 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.
I'm teaching myself Objective-C from a book (Cocoa programming for mac OS X) and am about halfway through however I have two questions that aren't answered or defined in the book.
When defining class methods what is the difference between (assuming there in a .h file):
- (int) population;
+ (int) population;
The way I see it at the moment is that - methods require the class to be allocated and initialized first however + can be called statically without requiring allocation and initialization. E.g. (in a function in another class)
// Using -
Earth *world = [[Earth alloc] init];
int population = [world population];
// Using +
int population = [Earth population];
If that is correct, when should I use static methods and are they're any disadvantages with doing so.
When defining a var in either a function paramater or as an actual var in a function, does the use of * mean the var will be an object? e.g. (again in a header file.)
- (void) setPopulation: (NSNumber *) population; //Use of * as population is of NSNumber
- (void) setPopulation: (int) population; // population isn't a class so doesn't need *
Sorry if any of my terms don't make sense in the land of Objective-C such as static methods, etc. I'm a PHP and Ruby Programmer.
The -/+ in method declarations for Objective-C simply denote whether the method is a class method or an instance method. For example, with Objective-C, you cannot send an instance a message that was declared as a class method. For example:
#interface MyObject : NSObject
-(void)myInstanceMethod;
+(void)myClassMethod;
#end
// ...
MyObject* obj = [[MyObject alloc] init];
[obj myInstanceMethod]; // this is okay
[obj myClassMethod]; // this will fail
[[obj class] myClassMethod]; // this is okay
[MyObject myClassMethod]; // this is okay
[MyObject myInstanceMethod]; // this will fail
As to the second part of your question, Objective-C is a strict super-set of C. It adds classes but they are really C data structures whose implementations are hidden from you by the Objective-C runtime. Because of this, classes are always represented as pointers. In C, the * means that the variable is being declared as a pointer to some memory address. You can use pointers with primitive types in C as well, but Objective-C objects must always be referred to by pointers.
There are many great tutorials/introductions to pointers out there. I would suggest simply googling for C tutorial and pointers to learn more.
The + declaration is a class method, you need no instance to call it. Constructors/factory methods need to be class methods. The - declared an instance method, operation on a single instance. Each instance has its own independent state (member variables). This is a fundamental difference in OO programming! In general make most methods instance methods, except for utility classes.
You can see some discussion of when to use static methods in When should I write Static Methods?