iOS Developer Library — Pre-Release

Developer

The Swift Programming Language

iBooks
On This Page

Declarations

A declaration introduces a new name or construct into your program. For example, you use declarations to introduce functions and methods, variables and constants, and to define new, named enumeration, structure, class, and protocol types. You can also use a declaration to extend the behavior of an existing named type and to import symbols into your program that are declared elsewhere.

In Swift, most declarations are also definitions in the sense that they are implemented or initialized at the same time they are declared. That said, because protocols don’t implement their members, most protocol members are declarations only. For convenience and because the distinction isn’t that important in Swift, the term declaration covers both declarations and definitions.

Grammar of a declaration

declaration import-declaration­

declaration constant-declaration­

declaration variable-declaration­

declaration typealias-declaration­

declaration function-declaration­

declaration enum-declaration­

declaration struct-declaration­

declaration class-declaration­

declaration protocol-declaration­

declaration initializer-declaration­

declaration deinitializer-declaration­

declaration extension-declaration­

declaration subscript-declaration­

declaration operator-declaration­

declarations declaration­declarations­opt­

Top-Level Code

The top-level code in a Swift source file consists of zero or more statements, declarations, and expressions. By default, variables, constants, and other named declarations that are declared at the top-level of a source file are accessible to code in every source file that is part of the same module. You can override this default behavior by marking the declaration with an access level modifier, as described in Access Control Levels.

Grammar of a top-level declaration

top-level-declaration statements­opt­

Code Blocks

A code block is used by a variety of declarations and control structures to group statements together. It has the following form:

  • {
  •     statements
  • }

The statements inside a code block include declarations, expressions, and other kinds of statements and are executed in order of their appearance in source code.

Grammar of a code block

code-block statements­opt­

Import Declaration

An import declaration lets you access symbols that are declared outside the current file. The basic form imports the entire module; it consists of the import keyword followed by a module name:

  • import module

Providing more detail limits which symbols are imported—you can specify a specific submodule or a specific declaration within a module or submodule. When this detailed form is used, only the imported symbol (and not the module that declares it) is made available in the current scope.

  • import import kind module.symbol name
  • import module.submodule

Grammar of an import declaration

import-declaration attributes­opt­import­import-kind­opt­import-path­

import-kind typealias­ struct­ class­ enum­ protocol­ var­ func­

import-path import-path-identifier­ import-path-identifier­import-path­

import-path-identifier identifier­ operator­

Constant Declaration

A constant declaration introduces a constant named value into your program. Constant declarations are declared using the keyword let and have the following form:

  • let constant name: type = expression

A constant declaration defines an immutable binding between the constant name and the value of the initializer expression; after the value of a constant is set, it cannot be changed. That said, if a constant is initialized with a class object, the object itself can change, but the binding between the constant name and the object it refers to can’t.

When a constant is declared at global scope, it must be initialized with a value. When a constant declaration occurs in the context of a class or structure declaration, it is considered a constant property. Constant declarations are not computed properties and therefore do not have getters or setters.

If the constant name of a constant declaration is a tuple pattern, the name of each item in the tuple is bound to the corresponding value in the initializer expression.

  • let (firstNumber, secondNumber) = (10, 42)

In this example, firstNumber is a named constant for the value 10, and secondNumber is a named constant for the value 42. Both constants can now be used independently:

  • println("The first number is \(firstNumber).")
  • // prints "The first number is 10."
  • println("The second number is \(secondNumber).")
  • // prints "The second number is 42."

The type annotation (: type) is optional in a constant declaration when the type of the constant name can be inferred, as described in Type Inference.

To declare a constant type property, mark the declaration with the static declaration modifier. Type properties are discussed in Type Properties.

For more information about constants and for guidance about when to use them, see Constants and Variables and Stored Properties.

Grammar of a constant declaration

constant-declaration attributes­opt­declaration-modifiers­opt­let­pattern-initializer-list­

pattern-initializer-list pattern-initializer­ pattern-initializer­pattern-initializer-list­

pattern-initializer pattern­initializer­opt­

initializer expression­

Variable Declaration

A variable declaration introduces a variable named value into your program and is declared using the keyword var.

Variable declarations have several forms that declare different kinds of named, mutable values, including stored and computed variables and properties, stored variable and property observers, and static variable properties. The appropriate form to use depends on the scope at which the variable is declared and the kind of variable you intend to declare.

You can override a property in a subclass by marking the subclass’s property declaration with the override declaration modifier, as described in Overriding.

Stored Variables and Stored Variable Properties

The following form declares a stored variable or stored variable property:

  • var variable name: type = expression

You define this form of a variable declaration at global scope, the local scope of a function, or in the context of a class or structure declaration. When a variable declaration of this form is declared at global scope or the local scope of a function, it is referred to as a stored variable. When it is declared in the context of a class or structure declaration, it is referred to as a stored variable property.

The initializer expression can’t be present in a protocol declaration, but in all other contexts, the initializer expression is optional. That said, if no initializer expression is present, the variable declaration must include an explicit type annotation (: type).

As with constant declarations, if the variable name is a tuple pattern, the name of each item in the tuple is bound to the corresponding value in the initializer expression.

As their names suggest, the value of a stored variable or a stored variable property is stored in memory.

Computed Variables and Computed Properties

The following form declares a computed variable or computed property:

  • var variable name: type {
  • get {
  •     statements
  • }
  • set(setter name) {
  •     statements
  • }
  • }

You define this form of a variable declaration at global scope, the local scope of a function, or in the context of a class, structure, enumeration, or extension declaration. When a variable declaration of this form is declared at global scope or the local scope of a function, it is referred to as a computed variable. When it is declared in the context of a class, structure, or extension declaration, it is referred to as a computed property.

The getter is used to read the value, and the setter is used to write the value. The setter clause is optional, and when only a getter is needed, you can omit both clauses and simply return the requested value directly, as described in Read-Only Computed Properties. But if you provide a setter clause, you must also provide a getter clause.

The setter name and enclosing parentheses is optional. If you provide a setter name, it is used as the name of the parameter to the setter. If you do not provide a setter name, the default parameter name to the setter is newValue, as described in Shorthand Setter Declaration.

Unlike stored named values and stored variable properties, the value of a computed named value or a computed property is not stored in memory.

For more information and to see examples of computed properties, see Computed Properties.

Stored Variable Observers and Property Observers

You can also declare a stored variable or property with willSet and didSet observers. A stored variable or property declared with observers has the following form:

  • var variable name: type = expression {
  • willSet(setter name) {
  •     statements
  • }
  • didSet(setter name) {
  •     statements
  • }
  • }

You define this form of a variable declaration at global scope, the local scope of a function, or in the context of a class or structure declaration. When a variable declaration of this form is declared at global scope or the local scope of a function, the observers are referred to as stored variable observers. When it is declared in the context of a class or structure declaration, the observers are referred to as property observers.

You can add property observers to any stored property. You can also add property observers to any inherited property (whether stored or computed) by overriding the property within a subclass, as described in Overriding Property Observers.

The initializer expression is optional in the context of a class or structure declaration, but required elsewhere. The type annotation is optional when the type can be inferred from the initializer expression.

The willSet and didSet observers provide a way to observe (and to respond appropriately) when the value of a variable or property is being set. The observers are not called when the variable or property is first initialized. Instead, they are called only when the value is set outside of an initialization context.

A willSet observer is called just before the value of the variable or property is set. The new value is passed to the willSet observer as a constant, and therefore it can’t be changed in the implementation of the willSet clause. The didSet observer is called immediately after the new value is set. In contrast to the willSet observer, the old value of the variable or property is passed to the didSet observer in case you still need access to it. That said, if you assign a value to a variable or property within its own didSet observer clause, that new value that you assign will replace the one that was just set and passed to the willSet observer.

The setter name and enclosing parentheses in the willSet and didSet clauses are optional. If you provide setter names, they are used as the parameter names to the willSet and didSet observers. If you do not provide setter names, the default parameter name to the willSet observer is newValue and the default parameter name to the didSet observer is oldValue.

The didSet clause is optional when you provide a willSet clause. Likewise, the willSet clause is optional when you provide a didSet clause.

For more information and to see an example of how to use property observers, see Property Observers.

Type Variable Properties

To declare a type variable property, mark the declaration with the static declaration modifier. Classes may mark type computed properties with the class declaration modifier instead to allow subclasses to override the superclass’s implementation. Type properties are discussed in Type Properties.

Grammar of a variable declaration

variable-declaration-head attributes­opt­declaration-modifiers­opt­var­

variable-name identifier­

getter-setter-block getter-clause­setter-clause­opt­

getter-setter-block setter-clause­getter-clause­

getter-clause attributes­opt­get­code-block­

setter-clause attributes­opt­set­setter-name­opt­code-block­

setter-name identifier­

getter-setter-keyword-block getter-keyword-clause­setter-keyword-clause­opt­

getter-setter-keyword-block setter-keyword-clause­getter-keyword-clause­

getter-keyword-clause attributes­opt­get­

setter-keyword-clause attributes­opt­set­

willSet-didSet-block willSet-clause­didSet-clause­opt­

willSet-didSet-block didSet-clause­willSet-clause­opt­

willSet-clause attributes­opt­willSet­setter-name­opt­code-block­

didSet-clause attributes­opt­didSet­setter-name­opt­code-block­

Type Alias Declaration

A type alias declaration introduces a named alias of an existing type into your program. Type alias declarations are declared using the keyword typealias and have the following form:

  • typealias name = existing type

After a type alias is declared, the aliased name can be used instead of the existing type everywhere in your program. The existing type can be a named type or a compound type. Type aliases do not create new types; they simply allow a name to refer to an existing type.

See also Protocol Associated Type Declaration.

Grammar of a type alias declaration

typealias-declaration typealias-head­typealias-assignment­

typealias-head attributes­opt­access-level-modifier­opt­typealias­typealias-name­

typealias-name identifier­

typealias-assignment type­

Function Declaration

A function declaration introduces a function or method into your program. A function declared in the context of class, structure, enumeration, or protocol is referred to as a method. Function declarations are declared using the keyword func and have the following form:

  • func function name(parameters) -> return type {
  •     statements
  • }

If the function has a return type of Void, the return type can be omitted as follows:

  • func function name(parameters) {
  •     statements
  • }

The type of each parameter must be included—it can’t be inferred. Although the parameters to a function are constants by default, you can write let in front of a parameter’s name to emphasize this behavior. Write var in front of a parameter’s name to make it a variable, scoping any changes made to the variable just to the function body, or write inout to make those changes also apply to the argument that was passed in the caller’s scope. For a discussion of in-out parameters, see In-Out Parameters.

Functions can return multiple values using a tuple type as the return type of the function.

A function definition can appear inside another function declaration. This kind of function is known as a nested function. For a discussion of nested functions, see Nested Functions.

Parameter Names

Function parameters are a comma separated list where each parameter has one of several forms. The order of arguments in a function call must match the order of parameters in the function’s declaration. The simplest entry in a parameter list has the following form:

  • parameter name: parameter type

For function parameters, the parameter name is used within the function body, but is not used when calling the function. For method parameters, the parameter name is used as within the function body, and is also used as a label for the argument when calling the method. The name of a method’s first parameter is used only within the function body, like the parameter of a function. For example:

  • func f(x: Int, y: String) -> String {
  • return y + String(x)
  • }
  • f(7, "hello") // x and y have no name
  • class C {
  • func f(x: Int, y: String) -> String {
  • return y + String(x)
  • }
  • }
  • let c = C()
  • c.f(7, y: "hello") // x has no name, y has a name

You can override the default behavior for how parameter names are used with one of the following forms:

  • external parameter name local parameter name: parameter type
  • #parameter name: parameter type
  • _ local parameter name: parameter type

A second name before the local parameter name gives the parameter an external name, which can be different from the local parameter name. The external parameter name must be used when the function is called. The corresponding argument must have the external name in function or method calls.

A hash symbol (#) before a parameter name indicates that the name should be used as both an external and a local parameter name. It has the same meaning as writing the local parameter name twice. The corresponding argument must have this name in function or method calls.

An underscore (_) before a local parameter name gives that parameter no name to be used in function calls. The corresponding argument must have no name in function or method calls.

Special Kinds of Parameters

Parameters can be ignored, take a variable number of values, and provide default values using the following forms:

  • _ : parameter type
  • parameter name: parameter type...
  • parameter name: parameter type = default argument value

A parameter named with an underscore (_) is explicitly ignored and can’t be accessed within the body of the function.

A parameter with a base type name followed immediately by three dots (...) is understood as a variadic parameter. A function can have at most one variadic parameter, which must be its last parameter. A variadic parameter is treated as an array that contains elements of the base type name. For instance, the variadic parameter Int... is treated as [Int]. For an example that uses a variadic parameter, see Variadic Parameters.

A parameter with an equals sign (=) and an expression after its type is understood to have a default value of the given expression. The given expression is evaluated when the function is called. If the parameter is omitted when calling the function, the default value is used instead. If the parameter is not omitted, it must have its name in the function call.

  • func f(x: Int = 42) -> Int { return x }
  • f() // Valid, uses default value
  • f(x: 7) // Valid, name and value provided
  • f(7) // Invalid, value provided without its name

Special Kinds of Methods

Methods on an enumeration or a structure that modify self must be marked with the mutating declaration modifier.

Methods that override a superclass method must be marked with the override declaration modifier. It’s a compile-time error to override a method without the override modifier or to use the override modifier on a method that doesn’t override a superclass method.

Methods associated with a type rather than an instance of a type must be marked with the static declaration modifier for enumerations and structures or the class declaration modifier for classes.

Curried Functions

You can rewrite a function that takes multiple parameters as an equivalent function that takes a single parameter and returns a function. The returned function takes the next parameter and returns another function. This continues until there are no remaining parameters, at which point the last function returns the return value of the original multiparameter function. The rewritten function is known as a curried function. For example, you can rewrite the addTwoInts function as the equivalent addTwoIntsCurried function:

  • func addTwoInts(a: Int, b: Int) -> Int {
  • return a + b
  • }
  • func addTwoIntsCurried(a: Int) -> (Int -> Int) {
  • func addTheOtherInt(b: Int) -> Int {
  • return a + b
  • }
  • return addTheOtherInt
  • }

The addTwoInts function takes two integers and returns the result of adding them together. The addTwoIntsCurried function takes a single integer, and returns another function that takes the second integer and adds it to the first. (The nested function captures the value of the first integer argument from the enclosing function.)

In Swift, you can write a curried function more concisely using the following syntax:

  • func function name(parameter)(parameter) -> return type {
  •     statements
  • }

For example, the following two declarations are equivalent:

  • func addTwoIntsCurried(a: Int)(b: Int) -> Int {
  • return a + b
  • }
  • func addTwoIntsCurried(a: Int) -> (Int -> Int) {
  • func addTheOtherInt(b: Int) -> Int {
  • return a + b
  • }
  • return addTheOtherInt
  • }

In order to use the addTwoIntsCurried function in the same way as the noncurried addTwoInts function, you must call the addTwoIntsCurried function with the first integer argument and then call its returned function with the second integer argument:

  • return a + b
  • }
  • func addTwoIntsCurried(a: Int)(b: Int) -> Int {
  • return a + b
  • }
  • addTwoInts(4, 5)
  • // returns a value of 9
  • addTwoIntsCurried(4)(b: 5)
  • // returns a value of 9

Although you must provide the arguments to a noncurried function all at once in a single call, you can use the curried form of a function to provide arguments in several function calls, one at a time (even in different places in your code). This is known as partial function application. For example, you can apply the addTwoIntsCurried function to an integer argument 1 and assign the result to the constant plusOne:

  • let plusOne = addTwoIntsCurried(1)
  • // plusOne is a function of type Int -> Int

Because plusOne refers to the addTwoIntsCurried function with its argument bound as the value 1, calling plusOne with an integer argument simply adds 1 to the argument.

  • plusOne(10)
  • // returns a value of 11

Grammar of a function declaration

function-head attributes­opt­declaration-modifiers­opt­func­

function-name identifier­ operator­

function-signature parameter-clauses­function-result­opt­

function-result ->­attributes­opt­type­

function-body code-block­

parameter-clauses parameter-clause­parameter-clauses­opt­

parameter-clause parameter-list­...­opt­

parameter-list parameter­ parameter­parameter-list­

parameter inout­opt­let­opt­opt­external-parameter-name­opt­local-parameter-name­type-annotation­default-argument-clause­opt­

parameter inout­opt­var­opt­external-parameter-name­opt­local-parameter-name­type-annotation­default-argument-clause­opt­

parameter attributes­opt­type­

external-parameter-name identifier­

local-parameter-name identifier­

default-argument-clause expression­

Enumeration Declaration

An enumeration declaration introduces a named enumeration type into your program.

Enumeration declarations have two basic forms and are declared using the keyword enum. The body of an enumeration declared using either form contains zero or more values—called enumeration cases—and any number of declarations, including computed properties, instance methods, type methods, initializers, type aliases, and even other enumeration, structure, and class declarations. Enumeration declarations can’t contain deinitializer or protocol declarations.

Enumeration types can adopt any number of protocols, but can’t inherit from classes, structures, or other enumerations.

Unlike classes and structures, enumeration types do not have an implicitly provided default initializer; all initializers must be declared explicitly. Initializers can delegate to other initializers in the enumeration, but the initialization process is complete only after an initializer assigns one of the enumeration cases to self.

Like structures but unlike classes, enumerations are value types; instances of an enumeration are copied when assigned to variables or constants, or when passed as arguments to a function call. For information about value types, see Structures and Enumerations Are Value Types.

You can extend the behavior of an enumeration type with an extension declaration, as discussed in Extension Declaration.

Enumerations with Cases of Any Type

The following form declares an enumeration type that contains enumeration cases of any type:

  • enum enumeration name: adopted protocols {
  •     case enumeration case 1
  •     case enumeration case 2(associated value types)
  • }

Enumerations declared in this form are sometimes called discriminated unions in other programming languages.

In this form, each case block consists of the keyword case followed by one or more enumeration cases, separated by commas. The name of each case must be unique. Each case can also specify that it stores values of a given type. These types are specified in the associated value types tuple, immediately following the name of the case. For more information and to see examples of cases with associated value types, see Associated Values.

Enumerations with Cases of a Raw-Value Type

The following form declares an enumeration type that contains enumeration cases of the same basic type:

  • enum enumeration name: raw-value type, adopted protocols {
  •     case enumeration case 1 = raw value 1
  •     case enumeration case 2 = raw value 2
  • }

In this form, each case block consists of the keyword case, followed by one or more enumeration cases, separated by commas. Unlike the cases in the first form, each case has an underlying value, called a raw value, of the same basic type. The type of these values is specified in the raw-value type and must represent an integer, floating-point number, string, or single character. In particular, the raw-value type must conform to the Equatable protocol and one of the following literal-convertible protocols: IntegerLiteralConvertible for integer literals, FloatingPointLiteralConvertible for floating-point literals, StringLiteralConvertible for string literals that contain any number of characters, and ExtendedGraphemeClusterLiteralConvertible for string literals that contain only a single character.

Each case must have a unique name and be assigned a unique raw value. If the raw-value type is specified as Int and you don’t assign a value to the cases explicitly, they are implicitly assigned the values 0, 1, 2, and so on. Each unassigned case of type Int is implicitly assigned a raw value that is automatically incremented from the raw value of the previous case.

  • enum ExampleEnum: Int {
  • case A, B, C = 5, D
  • }

In the above example, the raw value of ExampleEnum.A is 0 and the value of ExampleEnum.B is 1. And because the value of ExampleEnum.C is explicitly set to 5, the value of ExampleEnum.D is automatically incremented from 5 and is therefore 6.

Enumerations that have cases of a raw-value type implicitly conform to the RawRepresentable protocol, defined in the Swift standard library. As a result, they have a rawValue property and a failable initializer with the signature init?(rawValue: RawValue). You can use the rawValue property to access the raw value of an enumeration case, as in ExampleEnum.B.rawValue. You can also use a raw value to find a corresponding case, if there is one, by calling the enumeration’s failable initializer, as in ExampleEnum(rawValue: 5), which returns an optional case. For more information and to see examples of cases with raw-value types, see Raw Values.

Accessing Enumeration Cases

To reference the case of an enumeration type, use dot (.) syntax, as in EnumerationType.EnumerationCase. When the enumeration type can be inferred from context, you can omit it (the dot is still required), as described in Enumeration Syntax and Implicit Member Expression.

To check the values of enumeration cases, use a switch statement, as shown in Matching Enumeration Values with a Switch Statement. The enumeration type is pattern-matched against the enumeration case patterns in the case blocks of the switch statement, as described in Enumeration Case Pattern.

Grammar of an enumeration declaration

enum-declaration attributes­opt­access-level-modifier­opt­union-style-enum­

enum-declaration attributes­opt­access-level-modifier­opt­raw-value-style-enum­

union-style-enum enum­enum-name­generic-parameter-clause­opt­type-inheritance-clause­opt­union-style-enum-members­opt­

union-style-enum-members union-style-enum-member­union-style-enum-members­opt­

union-style-enum-member declaration­ union-style-enum-case-clause­

union-style-enum-case-clause attributes­opt­case­union-style-enum-case-list­

union-style-enum-case-list union-style-enum-case­ union-style-enum-case­union-style-enum-case-list­

union-style-enum-case enum-case-name­tuple-type­opt­

enum-name identifier­

enum-case-name identifier­

raw-value-style-enum enum­enum-name­generic-parameter-clause­opt­type-inheritance-clause­raw-value-style-enum-members­

raw-value-style-enum-members raw-value-style-enum-member­raw-value-style-enum-members­opt­

raw-value-style-enum-member declaration­ raw-value-style-enum-case-clause­

raw-value-style-enum-case-clause attributes­opt­case­raw-value-style-enum-case-list­

raw-value-style-enum-case-list raw-value-style-enum-case­ raw-value-style-enum-case­raw-value-style-enum-case-list­

raw-value-style-enum-case enum-case-name­raw-value-assignment­opt­

raw-value-assignment raw-value-literal­

raw-value-literal numeric-literal­ string-literal­ boolean-literal­

Structure Declaration

A structure declaration introduces a named structure type into your program. Structure declarations are declared using the keyword struct and have the following form:

  • struct structure name: adopted protocols {
  •     declarations
  • }

The body of a structure contains zero or more declarations. These declarations can include both stored and computed properties, type properties, instance methods, type methods, initializers, subscripts, type aliases, and even other structure, class, and enumeration declarations. Structure declarations can’t contain deinitializer or protocol declarations. For a discussion and several examples of structures that include various kinds of declarations, see Classes and Structures.

Structure types can adopt any number of protocols, but can’t inherit from classes, enumerations, or other structures.

There are three ways create an instance of a previously declared structure:

  • Call one of the initializers declared within the structure, as described in Initializers.

  • If no initializers are declared, call the structure’s memberwise initializer, as described in Memberwise Initializers for Structure Types.

  • If no initializers are declared, and all properties of the structure declaration were given initial values, call the structure’s default initializer, as described in Default Initializers.

The process of initializing a structure’s declared properties is described in Initialization.

Properties of a structure instance can be accessed using dot (.) syntax, as described in Accessing Properties.

Structures are value types; instances of a structure are copied when assigned to variables or constants, or when passed as arguments to a function call. For information about value types, see Structures and Enumerations Are Value Types.

You can extend the behavior of a structure type with an extension declaration, as discussed in Extension Declaration.

Grammar of a structure declaration

struct-declaration attributes­opt­access-level-modifier­opt­struct­struct-name­generic-parameter-clause­opt­type-inheritance-clause­opt­struct-body­

struct-name identifier­

struct-body declarations­opt­

Class Declaration

A class declaration introduces a named class type into your program. Class declarations are declared using the keyword class and have the following form:

  • class class name: superclass, adopted protocols {
  •     declarations
  • }

The body of a class contains zero or more declarations. These declarations can include both stored and computed properties, instance methods, type methods, initializers, a single deinitializer, subscripts, type aliases, and even other class, structure, and enumeration declarations. Class declarations can’t contain protocol declarations. For a discussion and several examples of classes that include various kinds of declarations, see Classes and Structures.

A class type can inherit from only one parent class, its superclass, but can adopt any number of protocols. The superclass appears first after the class name and colon, followed by any adopted protocols. Generic classes can inherit from other generic and nongeneric classes, but a nongeneric class can inherit only from other nongeneric classes. When you write the name of a generic superclass class after the colon, you must include the full name of that generic class, including its generic parameter clause.

As discussed in Initializer Declaration, classes can have designated and convenience initializers. The designated initializer of a class must initialize all of the class’s declared properties and it must do so before calling any of its superclass’s designated initializers.

A class can override properties, methods, subscripts, and initializers of its superclass. Overridden properties, methods, subscripts, and designated initializers must be marked with the override declaration modifier.

To require that subclasses implement a superclass’s initializer, mark the superclass’s initializer with the required declaration modifier. The subclass’s implementation of that initializer must also be marked with the required declaration modifier.

Although properties and methods declared in the superclass are inherited by the current class, designated initializers declared in the superclass are not. That said, if the current class overrides all of the superclass’s designated initializers, it inherits the superclass’s convenience initializers. Swift classes do not inherit from a universal base class.

There are two ways create an instance of a previously declared class:

  • Call one of the initializers declared within the class, as described in Initializers.

  • If no initializers are declared, and all properties of the class declaration were given initial values, call the class’s default initializer, as described in Default Initializers.

Access properties of a class instance with dot (.) syntax, as described in Accessing Properties.

Classes are reference types; instances of a class are referred to, rather than copied, when assigned to variables or constants, or when passed as arguments to a function call. For information about reference types, see Structures and Enumerations Are Value Types.

You can extend the behavior of a class type with an extension declaration, as discussed in Extension Declaration.

Grammar of a class declaration

class-declaration attributes­opt­access-level-modifier­opt­class­class-name­generic-parameter-clause­opt­type-inheritance-clause­opt­class-body­

class-name identifier­

class-body declarations­opt­

Protocol Declaration

A protocol declaration introduces a named protocol type into your program. Protocol declarations are declared at global scope using the keyword protocol and have the following form:

  • protocol protocol name: inherited protocols {
  •     protocol member declarations
  • }

The body of a protocol contains zero or more protocol member declarations, which describe the conformance requirements that any type adopting the protocol must fulfill. In particular, a protocol can declare that conforming types must implement certain properties, methods, initializers, and subscripts. Protocols can also declare special kinds of type aliases, called associated types, that can specify relationships among the various declarations of the protocol. Protocol declarations can’t contain class, structure, enumeration, or other protocol declarations. The protocol member declarations are discussed in detail below.

Protocol types can inherit from any number of other protocols. When a protocol type inherits from other protocols, the set of requirements from those other protocols are aggregated, and any type that inherits from the current protocol must conform to all those requirements. For an example of how to use protocol inheritance, see Protocol Inheritance.

You can add protocol conformance to a previously declared type by adopting the protocol in an extension declaration of that type. In the extension, you must implement all of the adopted protocol’s requirements. If the type already implements all of the requirements, you can leave the body of the extension declaration empty.

By default, types that conform to a protocol must implement all properties, methods, and subscripts declared in the protocol. That said, you can mark these protocol member declarations with the optional declaration modifier to specify that their implementation by a conforming type is optional. The optional modifier can be applied only to protocols that are marked with the objc attribute. As a result, only class types can adopt and conform to a protocol that contains optional member requirements. For more information about how to use the optional declaration modifier and for guidance about how to access optional protocol members—for example, when you’re not sure whether a conforming type implements them—see Optional Protocol Requirements.

To restrict the adoption of a protocol to class types only, mark the protocol with the class requirement by writing the class keyword as the first item in the inherited protocols list after the colon. For example, the following protocol can be adopted only by class types:

  • protocol SomeProtocol: class {
  • /* Protocol members go here */
  • }

Any protocol that inherits from a protocol that’s marked with the class requirement can likewise be adopted only by class types.

Protocols are named types, and thus they can appear in all the same places in your code as other named types, as discussed in Protocols as Types. However, you can’t construct an instance of a protocol, because protocols do not actually provide the implementations for the requirements they specify.

You can use protocols to declare which methods a delegate of a class or structure should implement, as described in Delegation.

Grammar of a protocol declaration

protocol-declaration attributes­opt­access-level-modifier­opt­protocol­protocol-name­type-inheritance-clause­opt­protocol-body­

protocol-name identifier­

protocol-body protocol-member-declarations­opt­

protocol-member-declaration protocol-property-declaration­

protocol-member-declaration protocol-method-declaration­

protocol-member-declaration protocol-initializer-declaration­

protocol-member-declaration protocol-subscript-declaration­

protocol-member-declaration protocol-associated-type-declaration­

protocol-member-declarations protocol-member-declaration­protocol-member-declarations­opt­

Protocol Property Declaration

Protocols declare that conforming types must implement a property by including a protocol property declaration in the body of the protocol declaration. Protocol property declarations have a special form of a variable declaration:

  • var property name: type { get set }

As with other protocol member declarations, these property declarations declare only the getter and setter requirements for types that conform to the protocol. As a result, you don’t implement the getter or setter directly in the protocol in which it is declared.

The getter and setter requirements can be satisfied by a conforming type in a variety of ways. If a property declaration includes both the get and set keywords, a conforming type can implement it with a stored variable property or a computed property that is both readable and writeable (that is, one that implements both a getter and a setter). However, that property declaration can’t be implemented as a constant property or a read-only computed property. If a property declaration includes only the get keyword, it can be implemented as any kind of property. For examples of conforming types that implement the property requirements of a protocol, see Property Requirements.

See also Variable Declaration.

Grammar of a protocol property declaration

Protocol Method Declaration

Protocols declare that conforming types must implement a method by including a protocol method declaration in the body of the protocol declaration. Protocol method declarations have the same form as function declarations, with two exceptions: They don’t include a function body, and you can’t provide any default parameter values as part of the function declaration. For examples of conforming types that implement the method requirements of a protocol, see Method Requirements.

To declare a class or static method requirement in a protocol declaration, mark the method declaration with the static declaration modifier. Classes that implement this method declare the method with the class modifier. Structures that implement it must declare the method with the static declaration modifier instead. If you’re implementing the method in an extension, use the class modifier if you’re extending a class and the static modifier if you’re extending a structure.

See also Function Declaration.

Grammar of a protocol method declaration

protocol-method-declaration function-head­function-name­generic-parameter-clause­opt­function-signature­

Protocol Initializer Declaration

Protocols declare that conforming types must implement an initializer by including a protocol initializer declaration in the body of the protocol declaration. Protocol initializer declarations have the same form as initializer declarations, except they don’t include the initializer’s body.

A conforming type can satisfy a nonfailable protocol initializer requirement by implementing a nonfailable initializer or an init! failable initializer. A conforming type can satisfy a failable protocol initializer requirement by implementing any kind of initializer.

When a class implements an initializer to satisfy a protocol’s initializer requirement, the initializer must be marked with the required declaration modifier if the class is not already marked with the final declaration modifier.

See also Initializer Declaration.

Grammar of a protocol initializer declaration

protocol-initializer-declaration initializer-head­generic-parameter-clause­opt­parameter-clause­

Protocol Subscript Declaration

Protocols declare that conforming types must implement a subscript by including a protocol subscript declaration in the body of the protocol declaration. Protocol subscript declarations have a special form of a subscript declaration:

  • subscript (parameters) -> return type { get set }

Subscript declarations only declare the minimum getter and setter implementation requirements for types that conform to the protocol. If the subscript declaration includes both the get and set keywords, a conforming type must implement both a getter and a setter clause. If the subscript declaration includes only the get keyword, a conforming type must implement at least a getter clause and optionally can implement a setter clause.

See also Subscript Declaration.

Grammar of a protocol subscript declaration

protocol-subscript-declaration subscript-head­subscript-result­getter-setter-keyword-block­

Protocol Associated Type Declaration

Protocols declare associated types using the keyword typealias. An associated type provides an alias for a type that is used as part of a protocol’s declaration. Associated types are similar to type parameters in generic parameter clauses, but they’re associated with Self in the protocol in which they’re declared. In that context, Self refers to the eventual type that conforms to the protocol. For more information and examples, see Associated Types.

See also Type Alias Declaration.

Grammar of a protocol associated type declaration

protocol-associated-type-declaration typealias-head­type-inheritance-clause­opt­typealias-assignment­opt­

Initializer Declaration

An initializer declaration introduces an initializer for a class, structure, or enumeration into your program. Initializer declarations are declared using the keyword init and have two basic forms.

Structure, enumeration, and class types can have any number of initializers, but the rules and associated behavior for class initializers are different. Unlike structures and enumerations, classes have two kinds of initializers: designated initializers and convenience initializers, as described in Initialization.

The following form declares initializers for structures, enumerations, and designated initializers of classes:

  • init(parameters) {
  •     statements
  • }

A designated initializer of a class initializes all of the class’s properties directly. It can’t call any other initializers of the same class, and if the class has a superclass, it must call one of the superclass’s designated initializers. If the class inherits any properties from its superclass, one of the superclass’s designated initializers must be called before any of these properties can be set or modified in the current class.

Designated initializers can be declared in the context of a class declaration only and therefore can’t be added to a class using an extension declaration.

Initializers in structures and enumerations can call other declared initializers to delegate part or all of the initialization process.

To declare convenience initializers for a class, mark the initializer declaration with the convenience declaration modifier.

  • convenience init(parameters) {
  •     statements
  • }

Convenience initializers can delegate the initialization process to another convenience initializer or to one of the class’s designated initializers. That said, the initialization processes must end with a call to a designated initializer that ultimately initializes the class’s properties. Convenience initializers can’t call a superclass’s initializers.

You can mark designated and convenience initializers with the required declaration modifier to require that every subclass implement the initializer. A subclass’s implementation of that initializer must also be marked with the required declaration modifier.

By default, initializers declared in a superclass are not inherited by subclasses. That said, if a subclass initializes all of its stored properties with default values and doesn’t define any initializers of its own, it inherits all of the superclass’s initializers. If the subclass overrides all of the superclass’s designated initializers, it inherits the superclass’s convenience initializers.

As with methods, properties, and subscripts, you need to mark overridden designated initializers with the override declaration modifier.

To see examples of initializers in various type declarations, see Initialization.

Failable Initializers

A failable initializer is a type of initializer that produces an optional instance or an implicitly unwrapped optional instance of the type the initializer is declared on. As a result, a failable initializer can return nil to indicate that initialization failed.

To declare a failable initializer that produces an optional instance, append a question mark to the init keyword in the initializer declaration (init?). To declare a failable initializer that produces an implicitly unwrapped optional instance, append an exclamation mark instead (init!). The example below shows an init? failable initializer that produces an optional instance of a structure.

  • struct SomeStruct {
  • let string: String
  • // produces an optional instance of 'SomeStruct'
  • init?(input: String) {
  • if input.isEmpty {
  • // discard 'self' and return 'nil'
  • return nil
  • }
  • string = input
  • }
  • }

You call an init? failable initializer in the same way that you call a nonfailable initializer, except that you must deal with the optionality of the result.

  • if let actualInstance = SomeStruct(input: "Hello") {
  • // do something with the instance of 'SomeStruct'
  • } else {
  • // initialization of 'SomeStruct' failed and the initializer returned 'nil'
  • }

A failable initializer of a structure or an enumeration can return nil at any point in the implementation of the initializer’s body. A failable initializer of a class, however, can return nil only after all stored properties of that class are initialized and self.init or super.init is called (that is, any initializer delegation is performed).

A failable initializer can delegate to any kind of initializer. A nonfailable initializer can delegate to another nonfailable initializer or to an init! failable initializer.

Initialization failure propagates through initializer delegation. Specifically, if a failable initializer delegates to an initializer that fails and returns nil, then the initializer that delegated also fails and implicitly returns nil. If a nonfailable initializer delegates to an init! failable initializer that fails and returns nil, then a runtime error is raised (as if you used the ! operator to unwrap an optional that has a nil value).

A failable designated initializer can be overridden in a subclass by any kind of designated initializer. A nonfailable designated initializer can be overridden in a subclass by a nonfailable designated initializer only.

For more information and to see examples of failable initializers, see Failable Initializers.

Grammar of an initializer declaration

initializer-declaration initializer-head­generic-parameter-clause­opt­parameter-clause­initializer-body­

initializer-head attributes­opt­declaration-modifiers­opt­init­

initializer-head attributes­opt­declaration-modifiers­opt­init­

initializer-head attributes­opt­declaration-modifiers­opt­init­

initializer-body code-block­

Deinitializer Declaration

A deinitializer declaration declares a deinitializer for a class type. Deinitializers take no parameters and have the following form:

  • deinit {
  •     statements
  • }

A deinitializer is called automatically when there are no longer any references to a class object, just before the class object is deallocated. A deinitializer can be declared only in the body of a class declaration—but not in an extension of a class—and each class can have at most one.

A subclass inherits its superclass’s deinitializer, which is implicitly called just before the subclass object is deallocated. The subclass object is not deallocated until all deinitializers in its inheritance chain have finished executing.

Deinitializers are not called directly.

For an example of how to use a deinitializer in a class declaration, see Deinitialization.

Grammar of a deinitializer declaration

deinitializer-declaration attributes­opt­deinit­code-block­

Extension Declaration

An extension declaration allows you to extend the behavior of existing class, structure, and enumeration types. Extension declarations are declared using the keyword extension and have the following form:

  • extension type name: adopted protocols {
  •     declarations
  • }

The body of an extension declaration contains zero or more declarations. These declarations can include computed properties, computed type properties, instance methods, type methods, initializers, subscript declarations, and even class, structure, and enumeration declarations. Extension declarations can’t contain deinitializer or protocol declarations, stored properties, property observers, or other extension declarations. For a discussion and several examples of extensions that include various kinds of declarations, see Extensions.

Extension declarations can add protocol conformance to an existing class, structure, and enumeration type in the adopted protocols. Extension declarations can’t add class inheritance to an existing class, and therefore you can specify only a list of protocols after the type name and colon.

Properties, methods, and initializers of an existing type can’t be overridden in an extension of that type.

Extension declarations can contain initializer declarations. That said, if the type you’re extending is defined in another module, an initializer declaration must delegate to an initializer already defined in that module to ensure members of that type are properly initialized.

Grammar of an extension declaration

extension-declaration access-level-modifier­opt­extension­type-identifier­type-inheritance-clause­opt­extension-body­

extension-body declarations­opt­

Subscript Declaration

A subscript declaration allows you to add subscripting support for objects of a particular type and are typically used to provide a convenient syntax for accessing the elements in a collection, list, or sequence. Subscript declarations are declared using the keyword subscript and have the following form:

  • subscript (parameters) -> return type {
  •     get {
  •         statements
  •     }
  •     set(setter name) {
  •         statements
  •     }
  • }

Subscript declarations can appear only in the context of a class, structure, enumeration, extension, or protocol declaration.

The parameters specify one or more indexes used to access elements of the corresponding type in a subscript expression (for example, the i in the expression object[i]). Although the indexes used to access the elements can be of any type, each parameter must include a type annotation to specify the type of each index. The return type specifies the type of the element being accessed.

As with computed properties, subscript declarations support reading and writing the value of the accessed elements. The getter is used to read the value, and the setter is used to write the value. The setter clause is optional, and when only a getter is needed, you can omit both clauses and simply return the requested value directly. That said, if you provide a setter clause, you must also provide a getter clause.

The setter name and enclosing parentheses are optional. If you provide a setter name, it is used as the name of the parameter to the setter. If you do not provide a setter name, the default parameter name to the setter is value. The type of the setter name must be the same as the return type.

You can overload a subscript declaration in the type in which it is declared, as long as the parameters or the return type differ from the one you’re overloading. You can also override a subscript declaration inherited from a superclass. When you do so, you must mark the overridden subscript declaration with the override declaration modifier.

You can also declare subscripts in the context of a protocol declaration, as described in Protocol Subscript Declaration.

For more information about subscripting and to see examples of subscript declarations, see Subscripts.

Grammar of a subscript declaration

subscript-declaration subscript-head­subscript-result­code-block­

subscript-declaration subscript-head­subscript-result­getter-setter-block­

subscript-declaration subscript-head­subscript-result­getter-setter-keyword-block­

subscript-head attributes­opt­declaration-modifiers­opt­subscript­parameter-clause­

subscript-result ->­attributes­opt­type­

Operator Declaration

An operator declaration introduces a new infix, prefix, or postfix operator into your program and is declared using the keyword operator.

You can declare operators of three different fixities: infix, prefix, and postfix. The fixity of an operator specifies the relative position of an operator to its operands.

There are three basic forms of an operator declaration, one for each fixity. The fixity of the operator is specified by marking the operator declaration with the infix, prefix, or postfix declaration modifier before the operator keyword. In each form, the name of the operator can contain only the operator characters defined in Operators.

The following form declares a new infix operator:

  • infix operator operator name {
  •     precedence precedence level
  •     associativity associativity
  • }

An infix operator is a binary operator that is written between its two operands, such as the familiar addition operator (+) in the expression 1 + 2.

Infix operators can optionally specify a precedence, associativity, or both.

The precedence of an operator specifies how tightly an operator binds to its operands in the absence of grouping parentheses. You specify the precedence of an operator by writing the context-sensitive keyword precedence followed by the precedence level. The precedence level can be any whole number (decimal integer) from 0 to 255; unlike decimal integer literals, it can’t contain any underscore characters. Although the precedence level is a specific number, it is significant only relative to another operator. That is, when two operators compete with each other for their operands, such as in the expression 2 + 3 * 5, the operator with the higher precedence level binds more tightly to its operands.

The associativity of an operator specifies how a sequence of operators with the same precedence level are grouped together in the absence of grouping parentheses. You specify the associativity of an operator by writing the context-sensitive keyword associativity followed by the associativity, which is one of the context-sensitive keywords left, right, or none. Operators that are left-associative group left-to-right. For example, the subtraction operator (-) is left-associative, and therefore the expression 4 - 5 - 6 is grouped as (4 - 5) - 6 and evaluates to -7. Operators that are right-associative group right-to-left, and operators that are specified with an associativity of none don’t associate at all. Nonassociative operators of the same precedence level can’t appear adjacent to each to other. For example, 1 < 2 < 3 is not a valid expression.

Infix operators that are declared without specifying a precedence or associativity are initialized with a precedence level of 100 and an associativity of none.

The following form declares a new prefix operator:

  • prefix operator operator name {}

A prefix operator is a unary operator that is written immediately before its operand, such as the prefix increment operator (++) is in the expression ++i.

Prefix operators declarations don’t specify a precedence level. Prefix operators are nonassociative.

The following form declares a new postfix operator:

  • postfix operator operator name {}

A postfix operator is a unary operator that is written immediately after its operand, such as the postfix increment operator (++) is in the expression i++.

As with prefix operators, postfix operator declarations don’t specify a precedence level. Postfix operators are nonassociative.

After declaring a new operator, you implement it by declaring a function that has the same name as the operator. If you’re implementing a prefix or postfix operator, you must also mark that function declaration with the corresponding prefix or postfix declaration modifier. If you’re implementing an infix operator, you don’t mark that function declaration with the infix declaration modifier. To see an example of how to create and implement a new operator, see Custom Operators.

Grammar of an operator declaration

prefix-operator-declaration prefix­operator­operator­

postfix-operator-declaration postfix­operator­operator­

infix-operator-declaration infix­operator­operator­infix-operator-attributes­opt­

infix-operator-attributes precedence-clause­opt­associativity-clause­opt­

precedence-clause precedence­precedence-level­

precedence-level A decimal integer between 0 and 255, inclusive

associativity-clause associativity­associativity­

associativity left­ right­ none­

Declaration Modifiers

Declaration modifiers are keywords or context-sensitive keywords that modify the behavior or meaning of a declaration. You specify a declaration modifier by writing the appropriate keyword or context-sensitive keyword between a declaration’s attributes (if any) and the keyword that introduces the declaration.

dynamic

Apply this modifier to any member of a class that can be represented by Objective-C. When you mark a member declaration with the dynamic modifier, access to that member is always dynamically dispatched using the Objective-C runtime. Access to that member is never inlined or devirtualized by the compiler.

Because declarations marked with the dynamic modifier are dispatched using the Objective-C runtime, they’re implicitly marked with the objc attribute.

final

Apply this modifier to a class or to a property, method, or subscript member of a class. It’s applied to a class to indicate that the class can’t be subclassed. It’s applied to a property, method, or subscript of a class to indicate that a class member can’t be overridden in any subclass.

lazy

Apply this modifier to a stored variable property of a class or structure to indicate that the property’s initial value is calculated and stored at most once, when the property is first accessed. For an example of how to use the lazy modifier, see Lazy Stored Properties.

optional

Apply this modifier to a protocol’s property, method, or subscript members to indicate that a conforming type isn’t required to implement those members.

You can apply the optional modifier only to protocols that are marked with the objc attribute. As a result, only class types can adopt and conform to a protocol that contains optional member requirements. For more information about how to use the optional modifier and for guidance about how to access optional protocol members—for example, when you’re not sure whether a conforming type implements them—see Optional Protocol Requirements.

required

Apply this modifier to a designated or convenience initializer of a class to indicate that every subclass must implement that initializer. The subclass’s implementation of that initializer must also be marked with the required modifier.

weak

The weak modifier is applied to a variable or a stored variable property to indicate that the variable or property has a weak reference to the object stored as its value. The type of the variable or property must be an optional class type. Use the weak modifier to avoid strong reference cycles. For an example and more information about the weak modifier, see Weak References.

Access Control Levels

Swift provides three levels of access control: public, internal, and private. You can mark a declaration with one of the access-level modifiers below to specify the declaration’s access level. Access control is discussed in detail in Access Control.

public

Apply this modifier to a declaration to indicate the declaration can be accessed by code in the same module as the declaration. Declarations marked with the public access-level modifier can also be accessed by code in a module that imports the module that contains that declaration.

internal

Apply this modifier to a declaration to indicate the declaration can be accessed only by code in the same module as the declaration. By default, most declarations are implicitly marked with the internal access-level modifier.

private

Apply this modifier to a declaration to indicate the declaration can be accessed only by code in the same source file as the declaration.

Each access-level modifier above optionally accepts a single argument, which consists of the keyword set enclosed in parentheses (for instance, private(set)). Use this form of an access-level modifier when you want to specify an access level for the setter of a variable or subscript that’s less than or equal to the access level of the variable or subscript itself, as discussed in Getters and Setters.

Grammar of a declaration modifier

declaration-modifier class­ convenience­ dynamic­ final­ infix­ lazy­ mutating­ nonmutating­ optional­ override­ postfix­ prefix­ required­ static­ unowned­ unowned­safe­ unowned­unsafe­ weak­

declaration-modifier access-level-modifier­

declaration-modifiers declaration-modifier­declaration-modifiers­opt­

access-level-modifier internal­ internal­set­

access-level-modifier private­ private­set­

access-level-modifier public­ public­set­

access-level-modifiers access-level-modifier­access-level-modifiers­opt­