| Since you used the word "delegation", I thought I'd mention the specific sense in which that word is used in Objective-C (and now in Swift). So in Objective-C (which is actually more "Smalltalk" than "Objective"), inheritance, while possible, is not the recommended way to build extensible objects. Instead the idea is for an object to "delegate" some decisions to another, unrelated object. There is no subclassing relationship, the word "delegate" here is used in quite the literal dictionary sense. Too many this and thats, so let me take an example. Suppose you have a list of elements you want to display on the screen. iOS provides a framework class called UITableView for this purpose. As the name suggests, it is a "Table" that displays a list of elements. Now, suppose you want to display a list of recent Hacker News posts. In many other mainstream languages, at this point the standard way to reuse the framework class would be to create our own subclass and override a few methods. So for example, we could have a HackerNewsTableView: UITableView {
override item(index i: Int) -> TableViewCell {
// return the row to display the post at index
...
}
Instead, the standard idiom in iOS programming is to have a separate "delegate" object implement the item method. i.e. We don't override the UITableView, but instead becomes it's delegate. Then when the table needs needs the row at some index i, it asks it'll ask us.This is a small and fairly straightforward thing, but it fundamentally results in a very different sort of programming style (which I personally think is under-appreciated outside of the iOS programming world, and maybe even within it). At no point does the original object know about who is its delegate, what type or class hierarchy it belongs to. In fact, it is common for a single "controller" object to be the delegate of many objects. And the core concept has nothing to do with iOS or Objective-C really. It can be done in any language that supports interfaces (they're called protocols in Objective-C, though in the general programming world the more common term is an interface, e.g. a Java interface). When you write a class, say Foo, you also write an associated interface, say FooDelegate. Then whoever wants to extend Foo can just implement the methods in FooDelegate, and at runtime set itself as the delegate of an instance of Foo. When foo needs something, it'll ask its delegate. This might seem backward/more work to you at first glance, but in practice it ends up being much simpler. And conceptually it is much closer to the Smalltalk philosophy, of there just being objects talking to each other. Foo ==> hey FooDelegate, do this for me ==> FooDelegate
Apologies in case you already know this. But I felt that in your article, you focused on two ways of doing delegation: inheritance and composition. But there is a third way, "delegation" itself. It seems too simple, but it works, it is the core organizing principle of iOS apps (or at least used to be, that's changing with the new SwiftUI framework). |