Subscripts

You've already used subscripts in Chapter 8, “Arrays” and Chapter 9, “Dictionaries” to retrieve the elements of arrays and dictionaries. It’s high time you learned to create your very own subscripts. Think of them as overloading the [] operator in order to provide shortcuts for accessing elements of a collection, class, structure or enumeration.

The subscript syntax is as follows:

subscript(parameterList) -> ReturnType { get {

// return someValue of ReturnType

}

set(newValue) {

// set someValue of ReturnType to newValue

}

}

As you can see, subscripts behave both like functions and computed properties:

  • The subscript’s prototype looks like a function’s signature — it has a parameter list and a return type, but instead of the func keyword and the function’s name, you use the subscript keyword. Subscripts may have variadic parameters, but can’t use inout or default parameters and can’t throw errors.

Note: You will learn more about errors in Chapter 22, “Error Handling”.

  • The subscript’s body looks like a computed property: it has both a getter and a setter. The setter is optional, so the subscript can be either read-write or read- only. The setter’s newValue default parameter can be omitted; its type is the same as the subscript’s return type and you should only declare it if you want to change its name to something else.

Enough theory! Add a subscript to a Person class defined as follows:

class Person {

let name: String let age: Int

init(name: String, age: Int) { self.name = name

self.age = age

}

}

The Person class has two stored properties — name of type String and age of type

Int, along with a designated initializer to kick things off.

Now suppose I want to create a version of myself right now, as follows:

let me = Person(name: "Cosmin", age: 30)

It would be nice to access my characteristics with a subscript like this:

me["name"]

me["age"]

me["gender"]

If you run this, Xcode would output the following error:

Type "Person" has no subscripts members

Whenever you use the square brackets operator, you actually call a subscript under the hood. Your class doesn’t have any subscripts defined by default, so you have to declare them yourself. Add the following code to the Person class with an extension like this:

extension Person {

subscript(key: String) -> String? { switch key {

case "name": return name

case "age": return "(age)"

default: return nil

}

}

}

The subscript returns an optional string based on the key you provide: you either return the key’s corresponding property’s value or nil if you don’t use a valid key. The switch must be exhaustive, so you need a default case. The subscript is read- only, so its entire body is a getter — you don’t need to explicitly state that with the get keyword.

The above test code works now:

me["name"]

me["age"]

me["gender"]

and outputs:

Cosmin 30

nil

That’s it!

Subscripts are easy to use and implement. They live somewhere between computed properties and functions. However, take care not to overuse them. Unlike computed properties and functions, subscripts have no name to make their intentions clear.

Subscripts are almost exclusively used to access the elements of a collection, so don't confuse the readers of your code by using them for something unrelated and unintuitive!

results matching ""

    No results matching ""