Operator Overloading in Swift Tutorial

Learn how to extend operators for new types or create entirely new operators in this new Swift tutorial! By Corinne Krych.

Leave a rating/review
Save for later
Share

Note from Ray: This is a brand new Swift tutorial released as part of the iOS 8 Feast. Enjoy!

As you’ve learned in earlier tutorials in the iOS 8 Feast, Swift offers many powerful modern programming features, such as generics, functional programming, first class enums and structs, and more.

But there’s another new feature of Swift that you should know and love: operator overloading!

This is a fancy way of saying you can make operators like +, -, /, or * to work with any type you’d like! You can even define your own operators if you’re feeling especially creative.

For example, we use operator overloading in our Swift Sprite Kit utility library to add and multiply CGPoints like this:

let pt1 = CGPoint(x: 10, y: 20)
let pt2 = CGPoint(x: -5, y: 0)
let pt3 = pt1 + pt2
let pt4 = pt3 * 100

Handy, eh? Get ready to overload your Swift development powers – to over 9,000!

Note: This Swift functional programming tutorial assumes you already know the basics of Swift development. If you are new to Swift, we recommend you check out some of our other Swift tutorials first.

Operators: An Overview

Note: This section is optional if you would like a review of operators and precedence. If you are already familiar with this, just create an empty playground and proceed to the next section: Overloading.

Begin by creating a new playground to help you explore operators.

Add the following line to your playground:

var simpleSum = 1 + 3

You’ll see the expected result:

4

There are two familiar operators in play here:

  1. First, you define a variable named simpleSum and set its value with the assignment operator (=).
  2. Second, you sum the two integers using the addition operator (+).

You’ll be overriding operators like these in this tutorial. But first, you need to understand the concept of precedence.

Precedence

You may remember from math class in school that rules of precedence apply to operators. These rules give some operators higher priority than others; higher-priority operators are applied first. For instance, you multiply before adding or subtracting.

Enter the following in your playground to confirm Swift operators follow these same rules:

var sumWithMultiplication = 1 + 3 - 3 * 2

You’ll see the following result:

-2

In cases where arithmetic operators have the same precedence, Swift evaluates the operators from left to right. In this example, this means operations are completed in the following order:

  1. 3 * 2: subtraction.
  2. 1 + 3: Because the leftmost operator is applied first for operations with equal precedence.
  3. 4 – 6: This operation is completed upon the results of the prior operations.
Note: If you want to see the full list of precedences rules in Swift, you can find a complete listing of operator precedence here.

Adding Isn’t Just for Ints

Integer arithmetic works as expected. But can you use the + operator for other types as well?

It turns out you can! Try it for yourself by adding this line to your playground:

var sumArray = [1, 2] + [1, 2]

You might expect this to add each element of the same position together. Instead, you’ll see something like this:

[1, 2, 1, 2]

In this case, Swift interprets the + as an append instruction. But what if you did want to add each element by position? This is known as vector addition.

Well, you could add a custom function to do this. Give it a try by adding the following to your playground:

func add(left: [Int], right: [Int]) -> [Int] {
    var sum = [Int]() 
    assert(left.count == right.count, "vector of same length only") 
    for (key, v) in enumerate(left) {
        sum.append(left[key] + right[key]) 
    }
    return sum
}

Here you define a global function that takes two integer arrays as input, checks that they have the same length, sums the values of each vector element and stores the resulting values in a new array.

Now add the following to confirm that your new function works:

var arr1 = [1, 1]
var arr2 = [1, 1]
var arr3 = add(arr1, arr2)

You’ll see the following in the console:

[2, 2]

It works! But rather than having to call a function do this, wouldn’t it be nice to use the + operator instead?

With Swift, this is possible—with the power of operator overloading!

Operator Overloading

Operator overloading allows you to change the way existing operators work with specific structures or classes. This is exactly what you need – you’d like to change the way the + operator works with Int arrays!

Because operator overloading is global to the playground scope, start with a new playground sheet to avoid impacting your earlier examples. Then add the following to your playground:

func +(left: [Int], right: [Int]) -> [Int] { // 1
    var sum = [Int]() // 2
    assert(left.count == right.count, "vector of same length only")  // 3
    for (key, v) in enumerate(left) {
      sum.append(left[key] + right[key]) // 4
    }
    return sum
}

You’ve just defined a global function called + that takes two Int arrays as input and returns a single Int array. Here’s a breakdown of how it works:

  1. Note there’s nothing fancy about this function definition. It’s a normal function definition except you use + for the name!
  2. Here you create an empty Int array.
  3. This sample will only work with input arrays of the same length, and this assert enforces that.
  4. You then enumerate through the left array, and sum each value with the corresponding value in the right array at the same position.

Test this function by adding the following to your playground:

var sumArray1 = [1, 2, 3] + [1, 2, 3]

Finally—the expected results of your vector addition operator! You will see the following in the console:

[2, 4, 6]

Of course, operator overloading isn’t all fun and games. It would be fairly confusing to someone jumping into your code if they were expecting the default behavior. For that matter, there’s nothing to stop you from overriding the + operator to, for example, perform subtraction on integers—the risks are obvious!

OperatorRage

Remember the operator overloading mantra: with great power comes great responsibility.

Typically, you’ll use overloading to extend an operation to a new object while maintaining the original semantics, rather than defining different (and confusing) behavior.

In this example, the behavior override does maintain semantics; vector addition is still a form of addition. But you may still want the ability to append arrays, and you want to avoid confusing yourself months down the road when you’ve forgotten you overrode the default behavior for Int arrays.

Fortunately, Swift lets you create your own custom operators.

Corinne Krych

Contributors

Corinne Krych

Author

Over 300 content creators. Join our team.