4

I am using Swift and am wondering about the concepts of Extension and Delegation. Recently I found a case where either one of these two concepts could be applied. This reminded of the "composition over inheritance" principle, which teaches that a "has-a" relationship may be preferred to a "is-a" relationship.

I encountered a case where it is always an object of some specific type that depends on an object conforming a certain protocol, therefore allowing both Extension and Delegation to be used.

For instance, I have a UIViewController that depends on a subclass of UIView. Say we take the following protocol:

protocol ViewInteraction {
  func interact()
}

This protocol will be conformed by the UIView subclass, say InteractedView. And any UIViewController may need to interact with this InteractedView.

In these types of situations, what's a good default - the Delegation pattern, or the Extension pattern? That is, should I use the Delegation pattern - letting the InteractedView conform it, and letting the UIViewController subclass manipulate a ViewInteraction property - or should I follow the Extension pattern and extend UIViewController to conform the ViewInteraction protocol (and call the InteractedView)?

  • Which way works better in your specific application? – Robert Harvey Feb 10 '16 at 22:50
  • @RobertHarvey So far it does not make a big difference. I like a bit more the delegation pattern because when I search for tools, e.g. a view, I would expect a catalog of all I have, not for extra behaviour on my object (in particular, I don't want to include extra tools that I don't need). But honestly, that's a detail. I don't know other pros or cons. – Vince Feb 11 '16 at 10:30
3

If each view controller needs to interact with a different ViewInteraction, then delegation is the obvious choice. If all view controllers need to interact with the same (global) ViewInteraction, or if the ViewInteraction is passed in as a parameter of a particular method and only used there, then extension might be better.

Some things to keep in mind. Extension methods are essentially the same as writing free functions. For example see the following:

class A {
}

extension A {
    func b() { print(self) }
}

func c(a: A) { print(a) }

The only difference between calling myA.b() and c(myA) is the syntax. Don't get me wrong, I'm not trying to belittle extensions. This syntax change can be a huge deal, especially if you are chaining methods. ( a.b().c(d) is far easier to read than c(b(a), d))

Keeping this in mind will hopefully help you in making your decision.

  • Importantly, delegation vs extension is not 'has-a' vs 'is-a'. Extension has nothing to do with the notion of 'is-a' because it isn't defining an inheritance relationship. – Daniel T. Mar 1 '16 at 2:51
  • "Extension is essentially the same as writing a free function." Can you explain what you mean by that? Extensions add members to their type. Methods in an extension of a class are the same as methods defined in the class's body. – Josh Caswell Mar 1 '16 at 4:43
  • 1
    @JoshCaswell You cannot add a property to a class using an extension, extension methods do not have privileged access to the class' properties, and extension methods cannot participate in dynamic dispatch unless they are part of the implementation of a protocol. In other words, extension methods are not "the same as methods defined in the class's body." As I show in the example, extension methods are semantically identical to free functions, but syntactically like member functions. Their only purpose is to adapt to protocols after the fact and pretty up the calling syntax. – Daniel T. Mar 1 '16 at 12:44
  • Okay, gotcha, I see what you're saying. Thanks for expanding. – Josh Caswell Mar 1 '16 at 18:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.