In a few of my recent posts, I outlined some things which I believe that Objective-C can learn from Java, the most recent discussing error handling. In order to avoid the impression that I may not like Objective-C, I figured I should outline some of what I believe are the most important improvements Objective-C has made.
Properties
When properties were first introduced, I read several who described them as simply syntax sugar. While they didn’t initially add much of anything that couldn’t already be done in the language before, they did yield one important feature: generated code. The code necessary in a setter, in particular the releasing of a previous value and setting the new value, was often fraught with errors. Despite code examples on a proper setter from Apple, I saw several cases where a setter failed to release the previous value, or retain the new value, or more commonly, do those two in the correct order. Enabling the compiler to generate this code for the programmer removed many of these errors.
Private Properties
In Java, a programmer can declare a private instance variable and subclasses cannot access it. Furthermore, a subclass can define its own instance variable with the same name and it will be completely separate from the parent’s instance variable. While private instance variables are supported in Objective-C, a child cannot create an instance variable with the same name. Fortunately, an update to properties did bring a way to accomplish the same thing.
A programmer can declare an interface in the .h file, then declare another interface in a class continuation in the .m file. Any properties declared in the .m file will not be visible to other classes, including subclasses. Combine this with the fact that you can create properties which are tied to instance variables which are not declared in the interface, and one can create private instance variables which are not visible to a subclass. There is one caveat though: If a parent class declares a property and a child of that class declares a property of the same name, the “private” property in the parent and the one in the child both reference the one in the child. On the other hand, referencing the instance variable generated by the property references different instance variables, even if the parent and child use the same name.
This little quirk can cause some interesting effects for one who is not aware of how the properties truly work. Accessing properties call selectors, and if a child declares the same property name, it synthesis selectors with the same name as the parent, thus overriding the parent. So, if you wish to have private instance variables which are inaccessible to a subclass, use a property declaration and access the instance variable. Be aware, due to the dynamic dispatch nature of Objective-C, one can still call the setter/getter selectors for the property which cannot be made private. If this is truly a concern, simply override the generated versions to do a different action.
Here is an example of a truly private instance variable. .h file:
@interface Parent : NSObject
@end
.m file:
@interface Parent ()
@property (strong) NSString *name;
@end
@implementation Parent
@synthesize name = name;
- (id)init
{
self = [super init];
if (self) {
name = @"Parent";
}
return self;
}
@end
Do the same in a child class, and you can see that the name instance variables in the child and parent are in fact, distinct.
Blocks
I’ve derided Objective-C before for its lack of inner classes, but with blocks, it is possible to essentially create an anonymous inner class with a single function. This effectively implements the Java equivalent of Runnable or Callable. I’m not going to go into too much detail, as anyone whose really used inner classes before knows how powerful they can be, but I figured it’d be important to point out that Objective-C has at least obtained some form of inner class. I would like to add that the fast enumeration with a block is really nice because in casses where a programmer needs the index of the current object, the block is given this information instead of having to track it manually.
BTW, I do know a technique for creating an inner class with multiple functions out of a block, but it’s just not worth it.
Collection Syntax
I cannot count the number of times I’ve used [NSArray arrayWithObjects:@"first", @"second", nil]
, but now Objective-C brings a nicer way to do this: @[@"first", @"second"]
. Yes, it is simply just more syntax sugar, but it is really convenient. Note, dictionaries have the same thing, but it is @{@"key":@"value"}
ARC
I saved the best for last; ARC is a big improvement for Objective-C. Not only does it remove a lot of the tedious nature of tracking retain/release, but it also introduces a few new constructs. If one wanted to override the setter for a property, the issue of retaining the new value, releasing the old, and getting the order correct is completely eliminated; ARC does all this busywork for you. Additionally, ARC generates a hard error if a programmer tries to call a selector which is not visible in the current context. So, in the example above, the selector name is implemented by the @synthesize
, but it is not declared in the interface. Before ARC, a programmer could go ahead and call it anyway, such as [parent name];
, and the compiler would generate a warning but it would work. With ARC, this generates a hard error because ARC needs to know if the selector returns a retained value, an autoreleased value, or no value at all. I view this as a good thing because I have known a few programmers who would call selectors not visible in the current context and then proceed to ignore the warnings. Most of these were simply forgetting the appropriate #include
, but in cleaning up these warnings, I often found misspellings just bidding their time, waiting to get executed, so they can spring into action and throw an exception brining down the program. Now, these warnings are errors, so in cleaning them up, programmers should find their true errors more easily and correct them sooner.
ARC also brings in weak references. Just like assignments, weak references do not prevent an object from being deallocated. They are different from assignments in that weak references will never give you an instance which has ben deallocated. I should add that weak references are not as powerful as the ones found in Java, but they do give most of the functionality. I had the task of trying to create a dictionary which holds the objects weakly, but since the keyspace is quite large, it also needs to clean itself up when the objects are deallocated. In Java, this can be accomplished with ReferenceQueues, but Objective-C is missing this feature. I did managed to come up with a more convoluted solution that works, but it’s not as pretty nor easy.
Interestingly, ARC now marks the third memory management model for Objective-C. The previous, GC, is now deprecated. I wonder how long till a new one replaces ARC. Maybe it’ll be ARC-GC, which combines ARC and GC and eliminates the whole problem of strong cycles.
Conclusion
While I’ve listed several places for Objective-C’s improvement before, it is not remaining stagnant. While I still contend that Java is the superior language, Objective-C does have the ability to change this. I should like to see the language improve even more so it can retain it’s position as the most popular langage for years to come.