I know Java, and now I'm learning Objective-C. What exactly are the differences between Java interfaces and Objective-C protocols?
They're pretty similar, although I think a class in Objective C can be considered to "implement" the protocol even if it doesn't explicitly declare that it does.
For example, in Java say you have interface X, which declares method m. If you also have a class which has a method with the same signature of m, the class doesn't actually implement interface X unless it specifically declares it. In Objective-C, this explicit declaration isn't necessary.
I think....
They are almost identical. However the one thing that has caught me out, is that unless you explicitly declare that an objective C protocol also implements NSObject, references to that protocol don't get access to the methods that NSObject declares (without a compiler warning anyway). With java you can have a reference to an interface, and still call toString() etc on it.
eg
Objective C:
@protocol MyProtocol
// Protocol definition
@end
id <MyProtocol> myProtocol;
[myProtocol retain] // Compiler warning
Java:
public interface MyInteface {
// interface definition
}
MyInterface myInterface;
myInterface.toString(); // Works fine.
Objective C (fixed):
@protocol MyProtocol <NSObject>
// Protocol definition
@end
id <MyProtocol> myProtocol;
[myProtocol retain] // No Warning
First off, a little historical perspective on the topic, from one of the creators of Java. Next, Wikipedia has a moderately helpful section on Objective-C protocols. In particular, understand that Objective-C supports both formal protocols (which are explicitly declared with the @protocol
keyword, the equivalent of a Java interface) and informal protocols (just one or more methods implemented by a class, which can be discovered via reflection).
If you adopt a formal protocol (Objective-C terminology for "implement an interface") the compiler will emit warnings for unimplemented methods, just as you would expect in Java. Unlike Java (as skaffman mentioned), if an Objective-C class implements the methods contained in a formal protocol, it is said to "conform" to that protocol, even if its interface doesn't explicitly adopt it. You can test protocol conformance in code (using -conformsToProtocol:) like this:
if ([myObject conformsToProtocol:@protocol(MyProtocol)]) {
...
}
With the advent of Objective-C 2.0 (in OS X 10.5 "Leopard" and iPhone OS), formal protocols can now define optional methods, and a class conforms to a protocol as long as it implements all the required methods. You use @required
and @optional
keywords to toggle whether the method declarations that follow must or may be implemented to conform to the protocol. (See the section of Apple's Objective-C 2.0 Programming Language guide that discusses optional protocol methods.)
Optional protocol methods open up a lot of flexibility to developers, particularly for implementing delegates and listeners. Instead of extending something like a MouseInputAdapter (which can be annoying, since Java is also single-inheritance) or implementing a lot of pointless, empty methods, you can adopt a protocol and implement only the optional methods you care about. With this pattern, the caller checks whether the method is implemented before invoking it (using -respondsToSelector) like so:
if ([myObject respondsToSelector:@selector(fillArray:withObject:)]) {
[myObject fillArray:anArray withObject:foo];
...
}
If the overhead of reflection becomes a problem, you can always cache the boolean result for reuse, but resist the urge to optimize prematurely. :-)