Extensions vs Operator overloading – a Beginner’s approach

February 2016

1. Introduction

Computer programming is about solving problems and getting things done the right way. However, as a beginner, you don’t care how you do it as long as you get it done. It works, so why bother tackling it in a completely different way after all?

The biggest challenge you face when discovering new programming paradigms is changing the way you think. This can be scary at first because you are used to doing things in a certain way and now you suddenly feel overwhelmed. It takes time and patience to get used to anything new but it’s worth doing it in the long run – being able to choose the right technique for a certain problem is a skill that any software developer should have in his toolbox.

2. The challenge

Your task for this tutorial is an easy one: add a certain amount of time to a given date so that the following code works:

var date = NSDate()
date = date + 60
date += 60

There are two approaches to the problem – operator overloading and extensions. Let’s dive into the first one.

3. Operator overloading

Operator overloading is one of the most powerful features of any programming language, so Apple decided to implement it in Swift. However, with great power comes great responsibility. You can easily design really weird scenarios with it, such as making the subtraction operator add numbers or the division one multiply them, but that is definitely not what you want to do with it.

OK, enough talking – let’s see what operator overloading is all about.

Fire up Xcode and open a playground. Delete everything from it and add this line to kick things off:

import Foundation

This imports the Foundation library into the playground – you use it to work with dates.
Next add the addition operator function’s prototype:

func +(lhs: NSDate, rhs: NSTimeInterval) -> NSDate {

}

The function has two parameters: the left hand side operand of type NSDate and the right hand side operand of type NSTimeInterval – this is just a fancy name for Double which reminds you that you are working with dates – and returns the addition result as a NSDate.

Note: You can read more about the class here.

Now add this to the function’s body:

return lhs.dateByAddingTimeInterval(rhs)

The dateByAddingTimeInterval(_:) method creates a new date from a given one by adding a certain amount of time, so you just return its output from the function.

Note: You can read more about the method here.

That’s it – time to implement the operator’s compound version!

Add the addition assignment operator function’s prototype at the end of the playground:

func +=(inout lhs: NSDate, rhs: NSTimeInterval) {

}

The function’s parameters have the same type as in the previous case. It doesn’t have a return type, because the left hand side operand is marked as inout – its value is modified and returned from the function.

Next use the dateByAddingTimeInterval(_:) method to add the operands like before:

lhs = lhs.dateByAddingTimeInterval(rhs)

That’s it – now let’s see the operators in action!

Add the following test code to the playground:

// 1
var date = NSDate()
// 2
date = date + 60
// 3
date += 60

Here’s what’s going on here, step-by-step:

  1. Create a brand new date from scratch with the NSDate class designated initialiser – it encapsulates the current date and time.
  2. Add a minute to it with the addition operator – the added value is measured in seconds.
  3. Add another minute to it with the addition assignment operator.

That’s really cool – however, if you’re not an operator overloading fan, check out the other approach with extensions.

4. Extensions

Extensions add functionality to a certain class without modifying it. Combined with protocols, they are a really powerful and flexible feature, so this is exactly what you are going to do here. Don’t worry, it’s easier than it sounds, so let’s dive in!

Note: You can read more about extensions here and protocols here.

Add the extension’s prototype to kick things off:

extension NSDate: Strideable {

}

You extend the NSDate class and implement the Strideable protocol as well. The protocol can be implemented by any type that may be measured – dates in our case.

Note: You can read more about the protocol here.

The protocol has two required methods – advancedBy(_:) and distanceTo(_:) – so let’s implement them in the extension.

public func advancedBy(n: NSTimeInterval) -> Self {

}

The advancedBy(_:) method is marked with the public access modifier since the Strideable protocol is marked as public also – any class can implement it. It takes an Int and returns Self – just a fancy way of saying that it returns the extension’s type, which is NSDate in this case. The new date is computed from the old one by adding a certain time interval to it.

Note: You can read more about the method here.

Next let’s use our good old friend, the dateByAddingTimeInterval(_:) method to add the given amount of time to the extension’s date and return the result from the advancedBy(_:) method:

return dateByAddingTimeInterval(n)

That’s it – now let’s move on to the distanceTo(_:) method’s implementation! Add its prototype to the extension:

public func distanceTo(other: NSDate) -> NSTimeInterval {

}

The method is marked as public as well. It takes a reference date and returns the amount of time between the original date and the reference one.

You can read more about the method here.

Now add this to the method’s body:

return other.timeIntervalSinceDate(self)

The timeIntervalSinceDate(_:) method computes the time interval between the reference date and the extension’s one – you access it with the self keyword – so you return its output from the distanceTo(_:) method.

You can read more about the method here.

That’s it – let’s use the extension – add this to the playground:

var time = NSDate()
time = time + 60
time += 60

It works exactly as before – add two minutes to the current date and time – way to go!

5. Conclusion

Both paradigms have their pros and cons – feel free to try them both and choose the one that suits you best. Happy coding! 🙂

Note: All the code in this tutorial was tested with a playground in Xcode 7.2 and Swift 2.1 (Download).

Note: The tutorial was inspired by a tweet made by Ray Fix, my Swift team lead at raywenderlich.com.

Advertisements
Posted in Swift

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Enter your email address to receive notifications of new posts by email.

Simple Programmer
%d bloggers like this: