Objective C protocols usage
I have a homework question which confused me, really badly. Below is a brief explanation of a question.
Imagine you are developing an application that stores contact information. The address book may contain many entity types e.g. Human being, a company or anything else that has a contact information.
- Now instead of explicitly checking every object type write a protocol that declares how an object must behave and successfully appear in your address book.
My understanding and efforts of answering this question is,
Build a protocol which has common methods of each type of contact information under
@required
tag. And all other methods which are not similar in different contact(Such as fax number has association with company but not person...) under @optional. At runtime you can check whether an object responds to any given method by usingselector
. Doubt : However this is again explicitly checking object type indirectly, am I right?My second thought is to use something like
abstract class
in java. Which means inherited class's from abstract class implements their own abstract methods. How e开发者_Go百科ver as a naive iOS developer I don't know how to implement this? and I am not sure whether this is going to solve my problem. I would like get enlighten if someone knows this.
External Reading done so far, Please let me know if the answer I am looking for is in one of these links. I will read it again to understand and solve this :). thanks.
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-TPXREF144
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-TPXREF146
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-TPXREF149
A protocol is the same thing as a Java interface. It just defines which methods the class should support. Here's a page that explains it clearly: http://www.otierney.net/objective-c.html#protocols
Essentially if you want to make sure a class will have a phoneNumber
method (accessor to the phoneNumber
property) you would do something like this:
@protocol ContactProtocol
-(void) phoneNumber;
@end
@interface Person: NSObject <ContactProtocol> {
...
}
@interface Company: NSObject <ContactProtocol> {
...
}
And then at compile time (or live for xcode 4) it will tell you if you forgot to add the phoneNumber
method to the Person
or Company
classes.
However this is again explicitly checking object type indirectly, am I right?
No, checking behavior is different from checking type. You can send -respondsToSelector:
to any object, and if the result is YES you can send the message regardless of the object's type. You can also require that an object implement a given protocol, again without caring about its actual type:
id<SomeProtocol> foo; // foo points to any type that implements SomeProtocol
My second thought is to use something like abstract class in java.
That could work, but it's apparently not what your assignment asked for, right? It says "...write a protocol..."
Objective-C doesn't provide a way to explicitly make a class abstract the way Java does. You just create the class, and if you don't want it to be instantiated directly you document that somewhere.
You have ... options.
Optional methods are convenient for the person writing the class to conform to the protocol, annoying for the person making use of the protocol. So it depends who you are trying to please.
Optional methods are not as bad as checking type. Imagine how the code would look when accessing a contactable entity object. When you use an optional method, you have to have an if case and an else case. It's not as convenient as just going ahead and assuming you can call the method. But it's way more convenient than checking type. That would be one if case for each different type of entity (and an else case, which might be an assertion). Additionally, if you use optional methods, information about the entity is encapsulated in its class. If you check type before calling a method, then the information about what type of contact information an entity provides is outside the class in the calling code. If you upgrade the entity to provide an additional type of contact, that improvement is not available until you update the calling code.
Option B is to make all the methods required, but give them the option of returning a value that indicates that no information is available, such as nil. Of course that still means an if case to check for a nil result, it's just less verbose. An even better solution for this problem is to have the methods return collections of multiple contacts. After all, people can have more than one phone number. Then to indicate that a contact type is not applicable, you would just return an empty collection.
The downside is that whoever writes the class that conforms to the protocol has to add a simple stub method that says return nil
or something.
精彩评论