There are a number of articles online that claim that neither Objective-C nor Java is better than the other, they’re just different. Well in terms of the mechanics and elegance of the language, I don’t agree– Java is the front-runner. Objective-C feels pretty archaic by comparison, and I suppose it truly is, being only a thin layer on top of standard ANSI C. Here are my top 10 gripes with Objective-C:
1. Lack of abstract/virtual classes and methods. Sometimes I want to ensure that a base class is never instantiated itself, other times I want to be sure that a subclass of a base class implements a particular method. In the case of the former, this is simply not possible– Objective-C has no concept of abstract classes. In the case of the latter, this is only achievable using protocols (i.e. similar to a Java interface) which seems slightly awkward- it requires considerably more code and bother than would be required of an abstract method in Java.
2. Lack of namespace support: It seems a bit silly that object types are prefaced with a Hungarian notation-like two characters indicating their source. The lack of namespaces also drastically increases the probability of naming collisions.
3. Header files… Groan. Defining an interface for every class is such a pain and requires so many more lines of code than are necessary. I find myself dreading every time I require a new class because of this and the fact that XCode’s code completion features are pitiful compared to Eclipse’s.
4. Managing memory: how I miss garbage collection.
5. Pointers: it is exceedingly rare that I would ever want or need to know the memory address of a variable, so why not abstract this information away? It’s easy to forget an * or @ and it can be difficult to debug problems relating to this.
6. Poor logging. NSLog is pretty poor and I haven’t been able to find anything like log4j for Objective-C.
7. Delegation, delelgation and more delegation. Objective-C makes huge use of the concept of delegation and I find that this can lead to spaghetti like code that can be difficult to follow.
8. Compiler reporting: Cryptic error messages and the poor logging described in 7 can make for challenging debugging.
9. Unit testing: OCUnit and OCMock are fairly immature compared to jUnit and jMock. And furthermore, a number of Cocoa classes include real work in their “constructors.” For instance, NSUrlConnection actually opens an HTTP connection and interacts online in its initWithRequest:delegate: method. The problem this creates is that object creation is tied to real work. This makes dependency injection difficult because we can’t separate the creation of the object from the logic, which would be required in order to substitute a test stub with test logic in its place. Dang. For more on this, see Misko Hevery’s great article on unit testing, object creation and logic.
10. No private methods. I often find myself in the position of using private methods within a class to define the specification of a procedure within that class… e.g.
doSomethingToData();
sendDataSomewhereElse();
These would all be private methods with the detail abstracted away. Unfortunately such methods need to be defined as part a class’s (public) interface even if only used within that class. Argh.
That’s it so far.. Feel free to add your own gripes in the comments.
You can actually do “private” methods like so -
In the .m file start a new interface with a different category above the implementation. The name of the category doesn’t matter, but people often use “private” or “Private” or something:
@interface FooClass(Private)
- (void) privateBarMethod;
@end
@implementation FooClass {
…
It’s a bit hackish, but at least you can specify the methods out of the main interface and still deal with the method as normal. Of course there’s nothing special about this “private” interface, it’s just a category, and any object could still send a message with performSelector: etc.