- Methods and Messages
- Interfaces and Implementations
- No Magic
- Memory Management
- Exceptions and Errors
- Overall
Interfaces and Implementations
Java has a well-defined bytecode. When you compile a .java file, you get a .class file containing the bytecode for the class. If you run JavaDoc, then you get an HTML description of the interface instead. You never need to specify the interface for a class to the compiler; it looks at the class file and generates it if it doesn't exist.
Objective-C uses the same compilation model as C. Files are separately compiled to object code, which is then linked together to form dynamic libraries, which are then linked together by the runtime loader. The compiler cannot read object code.
If you want to use a class from another class, then you usually need to provide the compiler with a description of that class's interface.
Every Objective-C class is described by both an interface and an implementation. The interface is usually stored in a header (.h) file, while the implementation is stored in a source (.m) file. This is only by convention: Remember that the preprocessor combines these files into a single compilation unit, so the compiler doesn't actually see them as separate files. A simple class might look like this:
@interface MyClass : NSObject { int integer; id object; } - (void)doSomethingWithThisFloat: (float)i; @end @implementation MyClass - (void)doSomethingWithThisFloat: (float)i { ... } @end
The first thing that you'll notice is that the instance variables are part of the interface. This is an artifact of how Objective-C objects were implemented. The first Objective-C implementations were simple preprocessors that generated C code, which was then compiled by the platform's native C compiler. Objects were defined as C structures by simply collecting all of their instance variables into a structure. Newer implementations support a non-fragile application binary interface (ABI), where instance variables are looked up by an offset variable, so the layout of the superclass does not have to be visible to a subclass.
You will also note the lack of any access modifiers. Objective-C supports these for instance variables, but they are trivial to bypass because they are not enforced at runtime. Instance variables are protected (accessible only by the class and subclasses) by default, and it is rare to change this.
Methods in Objective-C are all public. Note, however, that the interface declaration only lists the methods that the object is guaranteed to implement; it is free to implement others. These can be called from outside, but you'll get a warning at compile time if you do.
Interfaces in Java are a direct analog of protocols in Objective-C. Categories do not have any direct analog. These are sets of methods that will be added to an existing class when it loads.
Categories let you define new methods, including replacing existing methods, on a class even without having the source code available.
One of the less advertised features of categories is that they can be used to make existing classes conform to new protocols (which can be tested at runtime). We do this in Etoile to make all of the standard collection classes conform to the ETCollection protocol, which includes methods for manipulating all of the collections with the same set of methods.
Categories are also used to define informal protocols. If you write a category interface on NSObject defining some methods, but no corresponding implementation, then the compiler will think that all NSObject subclasses implement those methods and not generate any warnings when you try to call them. This is useful for delegates. You typically call delegate methods like this:
if ([delegate respondsToSelector: @selector(doSomethingForObjec:)]) { [delegate doSomethingForObject: self]; }
In Java, the delegate would typically implement an interface, so you'd have a number of methods where the implementation is empty. In Objective-C, you typically specify the required methods with a formal protocol and the optional ones with an informal protocol. With Objective-C 2, Apple introduced optional methods in formal protocols, which have the same effect but can be introspected at runtime.