Dec 27th, 2010 by Graham Booker
This is the second is a series of blog posts I’m writing on things that Objective-C can learn from Java. The other parts can be found here:
Part 1 (Generics)
Part 2 (Abstract Classes)
Part 3 (Single Source File)
Part 4 (Namespace)
Part 5 (Exceptions)
When one is using object oriented design, a common practice is to lump similar classes together with a common super-class and include the common functionality in that super-class. In doing such design, a common problem is for the super-class to require some information that can only be computed by the sub-class. The solution is for the super-class to make a function call on itself which the sub-class implements. For example, I recently designed a class which simplifies storage of an object in a SQL row, but it knows nothing about the actual field names or values stored in the database. In this case, I made a function, which subclasses implement, to retrieve this data. In Java, this is simply done through an abstract method in an abstract class.
Objective-C has no concept of an abstract method or class. Instead, the closest one can get is to provide an empty implementation for a function and then override that implementation in the sub-classes. Unlike Java, there is no error, or even a warning, if the programmer of the subclass forgets to implement the function that must be overridden. The landscape becomes more confusing when one considers properties. Since Objective-C’s gives errors when an implementation doesn’t provide the property accessor methods, it provides a annotation
@dynamic which silences the error. Apple mentions this can be used when an implementation is dynamically provided at runtime, but considering the complexity of this technique, it’s more common use is to silence the error in the case where a subclass implements the accessor methods. However, in the inconsistency with which Apple has treated properties, there is no error or warning, or any way to make the compiler throw one, if the sub-class programmer forgets the implementation. This makes
@dynamic really dangerous (just as ignoring warnings can be dangerous).
So, what is really required to make abstract classes work in Objective-C? Again, all of the work is in the compiler and doesn’t affect runtime. First, one needs to be able to define a class as abstract, which tells the complier that allocation of that class, such as
[AbstractClass alloc], should throw an error. Second, properties and methods need to be able to be defined as abstract. This will silence any errors and warnings about missing implementation in the abstract class and throw the errors and warnings about missing implementation in a non-abstract sub-class. A few changes to the complier, and a programmer can do more advanced designs and avoid simple common mistakes at compile time rather than runtime.
Impact on Runtime:
None, abstract classes and methods are syntax sugar only.
Impact on Code:
Allows more advanced design, and sub-classes become less prone to error.