There are a lot of new people who have jumped into Objective-C programming due to the popularity of iOS. This has caused a large amount of blogs from people who have just started with Objective-C about how horrible it is and how much better Java is, and that Apple has made a really stupid mistake basing their development on this archaic programming language which would be best left on history’s garbage heap.
I think a lot of the criticism is quit unfair, and I would like to use the opportunity to argue why I think Objective-C is a good choice for Apple and why I prefer it over Java. I am not claiming a balanced comparison here since this is mainly about emphasizing the good parts of Objective-C.
By using blocks and Grand Central dispatch is easy to use extra cores and avoid blocking when doing IO. Since Grand Central dispatch exists at the operating system level is possible to do load-balancing across the whole operating system. This is possible because one can optimize the number of threads being used for the number cores available. In Java are you won’t know how many threads are being used by other programs so it’s hard to know the optimal number of threads for your program.
Blocks and queues also makes it easy to avoid using critical sections to handle access to share resources by multiple threads. Java on the other hand you will be more dependent on Mutexes and locks which are harder to work with and scale does not scale as well.
A problem I have encountering number times when working with big software is that virtual methods could called and constructors. In languages such as Java, C# and C++ this will cause a number of problems. Those programs are really hard to do to debug and figure out. The problem arise because the virtual method gets called before the instance has been fully constructed. That means in Java’s case that variables have not been initialized.
Another problem with constructors is that they often lead to a lot of duplication of code. You can not reuse or call a constructor in the same way as you can call another method. All these problems are nonexistent in Objective-C because objective-C does not use constructors. In Objective-C instances are initialize with regular methods. That means calling virtual methods during initialization is not a problem. It also means that it’s easy to reuse initializer’s defined in the same class. This facilitates code reuse.
In Objective-C methods are invoked through message passing. In a nutshell that means sending a text string to an object and the object will look at the string and decide which method should be called.
This allows you to do a number things which are difficult to achieve in a statically typed language such as Java. Core data is a framework that utilizes this behavior. It is a framework that manages objects graphs and serialization. Objects are lazy loaded off disk as they are needed. The initial object loaded will point to proxy objects. As soon as one tries to do something with them Core Data will load from disk and replace the proxy objects with concrete objects.
Another example of where dynamic typing shines is constructing user interfaces. In user interfaces objects need to be loosely coupled. To see makes it easy to connect the actions of a user interface element to a method in an arbitrary class. This gets cumbersome in Java because the user interface elements requires the objects they interact with to have well defined static interfaces. It also allows you to do a number of other things which are very helpful when designing user interfaces, such as bindings and undo. With bindings you can tie a value of one objects to a user interface element. Undo is easy to achieve because method indications can easily be stored.
The delegate pattern also becomes more powerful because the class can check if the delegate implements a method or not if it doesn’t the class can choose to do the job itself. You can’t check in Java if the delegates implements a method or not.
Automatic reference counting versus garbage collection
No doubt garbage collection has its merits, but it’s not a silver bullet. Automatic reference counted a supported in Objective-C has a number of advantages. It requires less memory and is deterministic. These are important things in mobile devices which often have little memory and where you want responsive and fluid interfaces. A garbage collector can kick in and make your user-interface jerky. With automatic reference counting I find that I have to think very little about memory management. In that respect is not very different from garbage collection.
There have been a number of performance comparisons between Java and Objective-C. Most of these are extremely unrealistic. Often they have been micro benchmarks and this crucially testing the message passing performance of Objective-C versus a message invocation in Java. I would claim that in a real-world setting Objective-C it will beat Java performance wise. The reason for this is that in most of the code you write the slow Objective-C message passing is not a bottleneck. Despite the fact that all the user-interface code an iPhone application is written in Objective-C one cannot see any clear performance problems from that. Quite the contrary these interfaces will usually be smoother than on an Android device.
Usually performance problems will come from specific sections of your code. The important thing then is to be able to optimize and and tune those parts. Objective-C is very strong in this respect because it allows you to effortlessly integrate with low level C code. You also have fine-tuned control over memory allocation and memory layout. This is one of the reasons why the Java version of Git despite heavy optimization never reach more than half the performance of the C implementation. Is mainly came down to the inability to control memory layout in Java. Cache misses have severe effects on performance in today’s computer architectures. To avoid them one has to place data which is used together, close in memory.
I think a good analogy here is computer games. I think you will dispute the computer games are some of the most high-performance Software that exists. Yet most of the behavior into games is written in script languages. Often very slow script languages. High performance is achieved by writing the critical parts of the game, the game engine in C or C++. The beauty of Objective-C is that is essentially puts a script language and C into one language and make them interop very easily.
I often see comparisons with Java where the author is complaining about the verbosity of Objective-C. however this often comes down to the fact that Cocoa has long descriptive method names. One could easily write new methods with short names. The language does not prevent you from doing it. However a lot of the verbosity of java is baked into the Java syntax, there is very little you can do about it.
I’m thinking of such things as inner classes and adapters. Private and public has to be specified for every class and method. Problems which in Objective-C could easily have been solved by using a function pointer or storing a selector requires a lot of machinery in Java because everything always has to be a class or object.
From my understanding Objective-C has more proper handling of floating point arithmetic and you don’t have the problem in Java that all types are signed. This cause problems when doing bit manipulation. Most of the time this is not a problem but specialized software or performance tuning you might need to do it.
I think it is natural that things like points, rectangles and vectors are value types. Meaning whenever you assign, you make a copy. In Java this is not the case. Even a simple data structure like a point is allocated on the head and passed around as a reference. There are other languages which use references for this kind of data as well, but then they typically make the data structures immutable so for practical purposes they act like value types. For this has been a common source of bugs since one easily ends up modifying an input parameter. In Objective-C you can easily use C structs to get value types. For more complex data types which makes sense to treat as value types it is common practice to have immutable versions.
Robustness and security
Objective-C gives you full access to operating system services. You can use all types of interprocess communication offered and gives full access to utilize functions that deal with processes such as fork. This is important for robustness and security because it allows you to split a program into several different processes. If one process dies it doesn’t take down the whole application. It also allows you use different privileges to different process to limit security holes. In the Java world it seems like the emphasis is on threads which offer no protection from bringing each other down.
The process abstraction is very important in providing robustness. That is why a language such as Erlang, which despite lacking static typing is used to create some of the most robust software that exists. Erlang is designed around creating lots of processes that communicate and can restart each other if one crashes.
Objective-C compares well with Java. There is no reason why you could not be as productive in Objective-C as in Java. Apple is doing the right thing in sticking with Objective-C. Going with Java would be a stupid choice. It would negate a lot of their advantages that they have in Cocoa which is in my opinion one of the best designed frameworks for Application development. Apple has already shown that it is possible to modernize Objective-C. If one should need more productive programming languages I think it would be better with MacRuby, F-Script and Nu because those languages are built on the Objective-C runtime and mesh well with Cocoa, because they are dynamic languages like Objective-C. Java would not fit in well, and we already saw have Java was a failure for Mac development. I don’t see why things would be different on iOS.
A somewhat valid argument is why should Apple go with an almost unknown language instead of Java which everybody already knows. That would make sense if they had started from scratch. But Apple didn’t. They had a framework (Cocoa) that had been built and polished over very many years. It would have been foolish to throw away that for the current fad.