15

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,

  1. 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 using selector. Doubt : However this is again explicitly checking object type indirectly, am I right?

  2. 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 ever 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.

  1. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-TPXREF144

  2. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-TPXREF146

  3. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-TPXREF149

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
TeaCupApp
  • 11,316
  • 18
  • 70
  • 150

3 Answers3

10

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.

Wayne
  • 59,728
  • 15
  • 131
  • 126
Matt Williamson
  • 39,165
  • 10
  • 64
  • 72
  • 6
    Protocols are not the same as abstract classes; they're instead analogous to interfaces in Java. When you derive a class from an abstract class, you inherit both the methods and their implementations. With an interface, you get only the declarations. The same is true with Obj-c protocols -- when you declare that a class implements a protocol, you have to supply the method implementations. – Caleb Oct 01 '11 at 02:07
  • You are absolutely right. I was thinking of interfaces! I'm updating my answer. – Matt Williamson Oct 01 '11 at 02:17
  • Link to Otierney.net is currently down. Here's a link to Google's cached, not sure how long it will work. http://webcache.googleusercontent.com/search?q=cache:QbGm74kZa1wJ:www.otierney.net/objective-c.html+&cd=1&hl=en&ct=clnk&gl=us – kevins Nov 23 '13 at 03:22
4

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.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • This question wasn't about Swift, but if it was then, please correct me if I'm wrong: Your first answer would be: Yes, now in Swift, protocol is a type and simply you do `delegate?.someMethod` while not being identical to `respondsToSelector` it will run the function if a delegate is set... 2nd question: (after reading your comment for the accepted answer) in Swift since you can also provide default implementations to protocols much like abstract class. – mfaani Dec 20 '16 at 15:54
  • 1
    @Honey This answer predates Swift, and should be read in that context. Same goes for my comment. And even if the question and answers were contemporaneous with Swift, the title of the question *clearly* says "Objective-C" and the question is tagged [tag:objective-c]. – Caleb Dec 20 '16 at 16:34
  • I truly know that, I was just asking about it's diff with Swift, There are answers in this subject and I was just checking if I was able to put everything together (especially along with your comment above) correctly. – mfaani Dec 20 '16 at 16:35
1

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.

morningstar
  • 8,952
  • 6
  • 31
  • 42