Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making best use of Objective-C dynamic features

Tags:

objective-c

I have been using Objective-C for a little while but being from a static type background (C#) I think I am using it in a very static way. Declaring objects as id feels alien to me and I can't see what the benefits are. Can anyone shine a light for me to get a better understanding of this?

like image 329
Ian1971 Avatar asked Jan 04 '10 11:01

Ian1971


3 Answers

Objective-C is kind of a hybrid language, in which you can be as dynamic and as static as you want. You can declare all the types of all the variables if you want, you can even declare delegate variables as NSObject<Protocol>* if you want. The id type works less as a real type and more like a hint to the compiler telling him "hey, I know what I'm doing, just trust me on this", making the compiler avoid any type checking on that particular variable.

The first obvious benefit of the Objective-C type system is that container types (NSArray, NSDictionary, NSSet) accept and return id types. This removes the need for templates and generics altogether (like in C++, Java and C#).

Even better, you can actually have containers with elements of any kind inside. As long as you know what goes inside, nobody will complain if you add two NSStrings, one NSNumber and an NSValue inside the same NSArray. You can do that in other languages, but you have to use the "Object" base class, or the void* type, and then you require to box and unbox (or cast up and down) variables in order to get the same behaviour. In Objective-C you just assign, which removes the noise generated by casting operators and boxing operations. Then you can ask "respondsToSelector:" or "class" to each object, in order to know the identity and the operations you can perform with them, at runtime. In Objective-C, reflection is a first class citizen.

Another benefit is the reduced compilation times; the compilation of an Objective-C program is in general much faster than its equivalent in C++, given that there aren't that many type checks performed, and much linking is done at runtime. The compiler trusts more the programmer.

Finally, Objective-C's dynamic type system makes possible to have a tool like Interface Builder. This is the main reason why Cocoa and Cocoa Touch has faster development times; the GUI can generate code with "id" types all over the place, and this is deserialized whenever the NIB is loaded in memory. The only language that comes close to Objective-C in terms of UI design experience is C# (and VB.NET, of course) but at the price of a much heavier application.

I personally prefer to work with a more static type checking, and I even turn on the "Treat Warnings as Errors" setting in the Objective-C compiler; I've written a blog post about it:

http://akosma.com/2009/07/16/objective-c-compiler-warnings/

This is particularly useful when you are working with developers who are new to the language. It makes the compiler whine more often than usual :)

Static type system pundits might disagree with all these points, arguing that static type checking allows for "intellisense" IDEs and better maintenance in general. I worked using .NET for years (2001 - 2006) and I must say that dynamic languages tend to produce less code, are easier to read, and in general, gives more freedom to work. The tradeoff (there's always a tradeoff) is that there is less information at compile time. But as I tend to say, compilers are a poor man's suite of tests. The best thing IMHO is to have a good suite of tests, and a good bunch of human testers torturing your code to find bugs, no matter what language you choose.

like image 188
Adrian Kosmaczewski Avatar answered Oct 21 '22 16:10

Adrian Kosmaczewski


Objective-C's dynamism shines not just in the fact that every object is an id. Rather, it shines in the power of the Objective-C runtime and the ease to use it. A few examples of clever uses of runtime by Apple itself:

DO allows you to set up an proxy object for an Obj-C object in a separate app / separate machine. This is done by intercepting all the message sent to the proxy object, packing it up, sending it to the other app, and invoking it there.

KVO is implemented by dynamically replacing the setter method so that it automatically notifies the observers. (Well it's in fact subtler than that...)

CoreData accessors are generated at run time for each subclass of NSManagedObject, etc.

And, you can use the runtime from your code, too. I once used it for a good effect, mimicking CoreData and generating accessors at the run time, and having only their declaration in the header file. Thus you can get the merit of both the static typing (compile time error from the declaration in the header) and the dynamism (runtime generation of methods).

Mike Ash has written an excellent series of blog posts on how the runtime works and how to use it effectively. You just have to read it! DO, KVO, message forwarding and more. There are also many other interesting posts on the net, like fun with kvc and higher-order messaging 1, 2.

like image 5
Yuji Avatar answered Oct 21 '22 15:10

Yuji


It’s actually rather rare that you would need to declare an object as type id, as you should generally know what type you are expecting. Sometimes you might use an id<Protocol> type, if you don’t know the actual type of an object but know that it should conform to a specific protocol.

Is there a particular scenario you are thinking of?

like image 3
Ciarán Walsh Avatar answered Oct 21 '22 17:10

Ciarán Walsh