• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Why use protocols?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Why use protocols?


  • Subject: Re: Why use protocols?
  • From: Ondra Cada <email@hidden>
  • Date: Wed, 18 May 2005 20:03:05 +0200

Matt,

On 18.5.2005, at 19:07, Matt Neuburg wrote:

Here's an example. I've subclassed NSTableColumn in order to override
dataCellForRow:. But I don't think it's my NSTableColumn subclass's job to
contain the implementation; it's my table data source's job. So all my
NSTableColumn subclass does is turn to the data source to get the answer:


@implementation MyTableColumn
- (id)dataCellForRow:(int)row {
    id ourDataSource = [[self tableView] dataSource];
    return [ourDataSource dataCellForRow: row sender: self];
}
@end

Now, how do we know that ourDataSource (which, it is important to stress,
could be any class whatever) implements dataCellForRow:sender:? And how does
the compiler know? A protocol solves both problems at once.

It does, but (in the Cocoa worlds) not quite the right way. It is better to use informal protocols here, and, where appropriate, check whether it responds to a given selector.


It prevents the
programmer from forgetting to implement dataCellForRow:sender: in the data
source class (it would be a disaster if the programmer forgot to do this);

It does not: only instead of forgeting to implement the method he forgets to add the protocol to the class declaration :)


and it shuts the compiler up by satisfying it that ourDataSource does in
fact implement it.


@protocol MyTableColumnDataSource
- (id) dataCellForRow: (int) row sender: (id) self;
@end

@implementation MyTableColumn
- (id)dataCellForRow:(int)row {
    id <MyTableColumnDataSource> ourDataSource = [[self tableView]
dataSource];

This would issue a warning anyway, unless you have overridden tableView to return id<MyTableColumnDataSource>. And, what's worse, it would not help a bit if the programmer forgot (to use the protocol and implement the method).


If you truly wanted to use formal protocols (which is not the best idea), you should check here and cast:

...
id ds=[[self tableView] dataSource];
if (![ds conformsToProtocol:@protocol(MyTableColumnDataSource)]) @throw @"Oops, not MyTableColumnDataSource"; //Q&D
id<MyTableColumnDataSource> myDs=(id<MyTableColumnDataSource>)ds;
...


    return [ourDataSource dataCellForRow: row sender: self];
}
@end

*Much* better solution would be something like this:

@interface NSObject (MyTableColumnDataSource)
-dataCellForRow:(int)row sender:sender; // it's not best practice to name an argument 'self'
@end


@implementation MyTableColumn
-dataCellForRow:(int)row {
  id ds=[[self tableView] dataSource];
  if ([ds respondsToSelector:@selector(dataCellForRow:sender:)])
    return [ds dataCellForRow:row sender:self];
  return [super dataCellForRow:row];
}
...

Note that not only this is more flexible (by automatically falling back to the standard NSTableColumn behaviour if the data source does not support the extension), but also it allows the programmer to use any existing data source: this might not be possible with a formal protocol conformance, if the programmer has no access to the controller sources:

#import "TheCurrentTableControllerWhoseSourcesIDontHave.h"

@implementation TheCurrentTableControllerWhoseSourcesIDontHave (MyTableColumnDataSource)
-dataCellForRow:(int)row sender:sender {
...
}
@end


This concept works excellently with informal protocols, but would not be (reasonably) possible with formal ones, since you can't (in an easy and clean way) add a protocol to a class which you are not compiling.
---
Ondra Čada
OCSoftware: email@hidden http://www.ocs.cz
private email@hidden http://www.ocs.cz/oc



_______________________________________________ Do not post admin requests to the list. They will be ignored. Cocoa-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: This email sent to email@hidden
References: 
 >Re: Why use protocols? (From: Matt Neuburg <email@hidden>)

  • Prev by Date: Re: CoreData and arrays owned by arrays...
  • Next by Date: Re: CIImage - saving the file?
  • Previous by thread: Re: Why use protocols?
  • Next by thread: Re: Why use protocols?
  • Index(es):
    • Date
    • Thread