Thursday, August 1, 2013

Objective-C, Generics, and Parametric Typing

One question I see frequently asked and mis-understood:

Does Objective-C has Generics like Java or C#? 
The short answer is ...
No, Objective-C does not currently support parametric typing for collection elements.
However, this topic is more complex than the question or many existing answers admit..
Parametric-Typing for collections in Objective-C would not be the same as Generics in C#/Java. For example, it is unlikely you would ever see Objective-C add the capability to assure every object added to a collection IS an NSArray type or subtype. Instead, Objective-C could (and IMO should) have the ability to assure every object in a collection CONFORMS to a protocol/interface. (i.e. that it implements a set of required methods)
Why?
Objective-C is a language built on protocol (interface) compatibility, NOT subtyping relationships. That is, objects are compatible if they have all the right methods, we don't look at or care about their actual types. In fact, looking at actual types is a very very bad practice in Obj-C and in highly discouraged. This notion is sometimes called "Duck Typing", because if it quacks like a duck, it's a duck. We don't care if it literally inherited from some specific duck or not. This prevents you from being saddled by someone elses implementation hierarchy. -- The result is that as long as an object coming out of the list has a draw:: method it works, we don't actually care if it is a subclass of some specific JimmyDrawableBase object.
This not only makes code more reusable, but it also encourages a slightly different (more functional?) type of problem decomposition, because you can't rely on objects being derived from a given base class and thus having a bunch of your base-class implementation forced into them.
I personally think it would be nice for the Obj-C compiler to have parametric checking of PROTOCOL*CONFORMANCE*. That is, to make a NSMutableArray which requires all objects placed in it conform to a given protocol (i.e. have a given set of required methods).
Sometimes even this more-flexible protocol-conformance checking is resisted by dynamic programming folks, and with sound reasons. Programmers often have a way of over-specifying conformance requirements.
For example, you might require a list contain objects conforming to the NSArray protocol/interface, but you might ACTUALLY only call two of those methods. This is over-conformance. Someone who wishes to stick a compatible item in your array is forced to implement a ton of methods you are not actually calling -- at least not yet (see next).
Google Go tries to solve this problem by inferring structural compatibility. That is, if you call draw() on items coming out of a list, then the compiler assures everything going into a list contains a draw() method. If it does not contain a draw() method, it's a compiler error to put it into the list. This prevents the code from simply causing the same error to occur at runtime. The problem with this is that it only works for whole-program compilation. If Google-Go could compile modular DLLs (which it can't), then it would run into the problem that there isn't a way for me to say objects in the list need to support a specific interface of three methods, even though I'm not calling them today, because I might call them in the future.
Between those two solution likes the tradeoff and the truth.
Personally, I would like to see Objective-C add parametric protocol conformance, so I could ask the compiler to assure the contents of a particular collection always conform to a given set of protocols.
I would also like the compiler to help me avoid over-conformance. If I'm not calling methods in those protocols on objects, it should generate errors/warnings telling me so. If I want to keep them in the protocol even though I'm not using them, I should have to explicitly make a declaration for each method in the protocol that it "might be used in the future, so elements all need to supply it now". This at least makes the process of over-conformance require MORE work, instead of Java/C# where it requires less work.

No comments:

Post a Comment