Reputation: 6176
i have been asked a question about delegates, and i had some doubts about the right answer :
When you create your own protocol, what makes the difference between using a delegate, or just instantiating the class, and call a simple method?
I thought: with the delegate, you don't bother instantiate a new whole class, and you can set the delegate outside the class, and just call the method with the "delegate". Is it also a good thing to use delegates to avoid the unlimited imports? as when classA imports classB, and if you instantiate the class instead of using delegates, classB also imports classA, and it causes a crash?
Are there any other good reasons when you create your own protocol/delegate?
Upvotes: 0
Views: 225
Reputation: 86651
I suppose the main advantage of delegates is that they allow you to change the behaviour of objects at run time. They also help enforce separation between functional areas.
Let's look at a concrete example: NSTableView
's data source. NSTableView
provides the UI implementation for a table in OS X. The data source delegate provides functionality for getting hold of the data to populate the table.
In the olden days before I came to Objective-C and programmed in C++ and Java, I would have implemented a table view by having the UI class with some protected methods for managing the data which would be subclassed to create different tables views.
This approach is perfectly valid but it mixes up functionality for managing the data with functionality for display and is not very flexible. Once you have said widget X is a table view which accesses data in a certain way, that is all set in stone. If you want widget X to get its data in a different way, you have to either build that flexibility into the UI class or destroy it and recreate it from a different subclass.
On the other hand, the delegate pattern allows NSTableView
to change its data source completely with a simple assignment and reload. Also, the UI class is not polluted with data handling code and the data handling class is not polluted with UI handling code.
You can do delegates without using protocols, and indeed, in pre-10.5 versions of Cocoa, this was the norm rather than the exception, but, if you use a protocol to define the delegate API you get compiler support for error checking your delegate implementation and a minimal level of documentation.
Upvotes: 1
Reputation: 12496
Well, look at an example.
Assume you have "something" that happens to display a window as part of whatever it's doing. Without delegates or a similar setup, you'd have to be a subclass of "Window" to be able to handle window stuff, and you'd have to be a subclass of something else to handle whatever else you're doing. So it's either not possible, or you get into all sorts of multiple inheritance weirdness.
Thus, you would probably end up making a subclass of whatever, and a sublcass of "Window", and instanciate objects for both, and have them communicate somehow. Which is exactly what a delegate does, except that you have to do it over and over again for all sorts of things. Like imagine a window with 10 buttons in it, each of which needs a button sublcass that doesn't really do all that much except for calling "ButtonXClicked" on your actual class. Again, see the "delegate" reimplemented here (yes, in Cocoa it's not a delegate; that would be the target/action. But it's not all that different from a delegate)?
Thus, delegates are pretty much a convenience to connect objects that don't really have a "kind of" relationship as implied by deriving classes.
It also allows you to connect objects that are "created elsewhere", like when you have something that creates an object and returns it to you: you can't really subsitute a subclass there, but the API might still allow you to do a "setDelegate:"-like thing to connect that object to your application.
Sometimes delegates are more appropiate, sometimes subclasses are better, and there's probably cases where it doesn't really matter.
Upvotes: 1
Reputation: 14841
The question is one of generalization. It's best to avoid unlimited imports.
Imagine this scenario. You have a timer (from a class called KDTimer) that runs, and expires at some point. Now you want to use it in 3 game modes A,B and C (which all correspond to 3 different classes). Now the different game modes will react differently to the expiration of the timer. The difference you get is:
Delegate:
You define your protocol in KDTimer, set a,b or c to be its delegate (actually a,b or c sets itself to be the timers delegate), and do
-(void) increaseProgress {
//incrementProgress
if(self.progress>=1)
[_delegate timeExpired];
}
And you're golden.
Non-Delegate:
#import "A"
#import "B"
#import "C"
@synthesize a,b,c;
-(void) increaseProgress {
//incrementProgress
if(self.progress>=1)
[self.a timeExpired];
[self.b timeExpired];
[self.c timeExpired];
//we don't really know which instance should be messaged
}
The point is, not using delegates can result in complex code, by using them, you get more reusable components. The timer doesn't need to know about the the game modes, it's just trying tell that it has expired.
Upvotes: 0