Skip to content
Theory · Protocols and generics · lesson 3 of 9

Extensions

The square already works as a shape, and now it turns out you also need its perimeter. You could go back to the declaration of Square and add a property. But what if the type belongs to someone else, like Int from the standard library? You cannot edit its declaration.

Let's go back to the job openings and picture a training course. An employee attends it, learns a new skill and comes back the same person, only with a new ability. Nobody has to rewrite their personnel file for that.

In Swift an extension plays the part of such a course: it adds abilities to a type that is already declared, even one you did not write.

Extending an existing type

Let's teach whole numbers two new things:

SWIFT
extension Int {
    var isEven: Bool { self % 2 == 0 }
    func squared() -> Int { self * self }
}

let n = 7
print(n.isEven, n.squared()) // false 49
print(4.isEven) // true

Let's go through the program line by line:

  1. extension Int opens an extension of the type Int. Everything inside the braces goes to every whole number.
  2. var isEven: Bool is a computed property. Here self is the number itself, the one the property was asked of.
  3. func squared() is a new method: the number multiplies itself.
  4. n.isEven and n.squared() are called as if they had been in Int from the start. Even the number 4 written right in the code now has isEven.

Here the training-course picture is inaccurate. One employee attends a course, while an extension teaches the whole type at once. Every number in the program gets the new ability, including the ones created above the extension line.

Extending your own type

You extend your own types the same way. Code is often split like this: the type's declaration holds its data, and an extension holds what the type can do with it.

SWIFT
struct Square {
    let side: Double
}

extension Square {
    var perimeter: Double { side * 4 }
}

print(Square(side: 3).perimeter) // 12.0

The properties from the declaration are visible inside an extension: perimeter computes from side, like an ordinary computed property.

Conformance in an extension

A badge can be earned at a course too. If a type was declared without a protocol, you add the conformance with an extension: write a colon and the protocol after the type's name, and meet its requirements inside.

SWIFT
protocol Shape {
    func area() -> Double
}

extension Square: Shape {
    func area() -> Double { side * side }
}

let shapes: [any Shape] = [Square(side: 3)]
print(shapes[0].area()) // 9.0

Square was declared without : Shape, and now the square conforms to the protocol and goes into an [any Shape] array. In the same way someone else's type can conform to your protocol: extension Int: Shape with an area() method inside leaves the declaration of Int unchanged but gives it the badge.

What you can add

Interviewers like to ask this: what can you add with an extension, and what can't you? Of what you already know, an extension can add:

  • computed properties;
  • methods;
  • type properties and type methods: static let and static func;
  • an init for a struct, and the memberwise initializer does not disappear;
  • protocol conformance.

An ordinary stored property, which every instance has its own copy of, cannot be added with an extension. This is a common mistake with extensions, and we'll look at it separately.

Common mistake

An extension trying to give the square a color:

SWIFT
extension Square {
    var color = "red" // ✗
}
TEXT
error: extensions must not contain stored properties

The program does not compile: an extension cannot add a stored instance property. Such properties make up the type's value itself, and the declaration sets their list. For example, an Int value takes 64 bits on computers and phones, and all the code that works with numbers relies on that. A static let type property, however, can be added by an extension: there is one for the whole type, and it is not part of any value.

An extension adds abilities, but it does not change what a value is made of: a course teaches a new skill, but it does not change the employee's height. The fix is to add var color = "red" to the declaration of Square, next to side.

Key points

  • An extension adds abilities to a type that is already declared, even someone else's, like Int, and every value of that type gets them.
  • An extension can add computed properties, methods, type properties and type methods, a struct's init and protocol conformance.
  • An extension cannot add an ordinary stored property: such properties make up the value, and only the type's declaration sets them.