id<Protocol>, Retain/Release and Protocol Inheritance
Paul Cantrell’s recent post showed that you can use Objective-C protocols to constrain the behavior of
id objects. When declaring an instance variable or parameter as
id<Protocol>, the compiler’s type checker will warn when sending message not found in
For this reason, protocols are pretty handy. But in practice, a problem arises. Let’s say you have a protocol defined as follows:
Now let’s say you have a member variable defined as conforming to
What happens if you try to
release the object? The compiler gives you a warning, because
MyProtocol doesn’t declare the
So what do we do about this? Perhaps your first instict is to manually declare the
release messages in your protocol:
- (oneway void)release;
But that seems tedious and hackish, doesn’t it? It’s hard to believe that would be the “correct” solution.
Or maybe you could declare
someVar slightly differently, like this:
This will get rid of the compiler warnings, but the syntax is pretty unwieldy and it still doesn’t feel right. None of the Apple-supplied classes use this syntax, after all.
You may have noticed that in addition to the NSObject class there’s an NSObject protocol which declares most of the methods found in NSObject. Using this knowledge, you could define
a little more elegantly:
But it still feels like we’re not there yet. Again, Apple doesn’t appear to use this form of declaration in their own classes.
Enter protocol inheritance. You can declare a protocol to inherit from another protocol as follows:
The above snippet declares a protocol named
Inherits containing a single method,
foo. In addition, the
Inherits protocol extends a protocol named
Base, thus all methods of base
Base are included in
Inherits as well.
Circling back to our original problem, the solution is now obvious: make
MyProtocol inherit from
Now an object of type
id<MyProtocol> will accept messages such as
release or even
performSelector:withObject:afterDelay: without generating compiler warnings.