Swift Chapter 8 2018-12-19T13:13:03+00:00

SWIFT CHAPTER 8

Topics: (Protocols, Delegation, Generics, Type Constraints)

Protocols

A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol.In addition to specifying requirements that conforming types must implement, you can extend a protocol to implement some of these requirements or to implement additional functionality that conforming types can take advantage of.

Protocol Syntax

You define protocols in a very similar way to classes, structures, and enumerations:

protocol SomeProtocol {
// protocol definition goes here
}
Custom types state that they adopt a particular protocol by placing the protocol’s name after the type’s name, separated by a colon, as part of their definition. Multiple protocols can be listed, and are separated by commas:

struct SomeStructure: , {
// structure definition goes here
}
If a class has a superclass, list the superclass name before any protocols it adopts, followed by a comma:

class SomeClass: , , {
// class definition goes here
}


Property Requirements

A protocol can require any conforming type to provide an instance property or type property with a particular name and type. The protocol doesn’t specify whether the property should be a stored property or a computed property—it only specifies the required property name and type. The protocol also specifies whether each property must be gettable or gettable and settable.If a protocol requires a property to be gettable and settable, that property requirement can’t be fulfilled by a constant stored property or a read-only computed property. If the protocol only requires a property to be gettable, the requirement can be satisfied by any kind of property, and it’s valid for the property to be also settable if this is useful for your own code.
Property requirements are always declared as variable properties, prefixed with the var keyword. Gettable and settable properties are indicated by writing { get set } after their type declaration, and gettable properties are indicated by writing { get }.

protocol SomeProtocol {
var mustBeSettable: { get set }
var doesNotNeedToBeSettable: { get }
}
Always prefix type property requirements with the static keyword when you define them in a protocol. This rule pertains even though type property requirements can be prefixed with the class or static keyword when implemented by a class:

protocol AnotherProtocol {
static var someTypeProperty: { get set }
}
Here’s an example of a protocol with a single instance property requirement:

protocol FullyNamed {
var fullName: { get }
}
The FullyNamed protocol requires a conforming type to provide a fully-qualified name. The protocol doesn’t specify anything else about the nature of the conforming type—it only specifies that the type must be able to provide a full name for itself. The protocol states that any FullyNamed type must have a gettable instance property called fullName, which is of type String.
Here’s an example of a simple structure that adopts and conforms to the FullyNamed protocol:

struct Person: {
var fullName:
}
let john = Person(fullName: “John Appleseed”)
// john.fullName is “John Appleseed”

This example defines a structure called Person, which represents a specific named person. It states that it adopts the FullyNamed protocol as part of the first line of its definition.Each instance of Person has a single stored property called fullName, which is of type String. This matches the single requirement of the FullyNamed protocol, and means that Person has correctly conformed to the protocol. (Swift reports an error at compile-time if a protocol requirement is not fulfilled.)
Here’s a more complex class, which also adopts and conforms to the FullyNamed protocol:

class Starship: {
var prefix: ?
var name:
init(name: , prefix: ? = nil) {
self.name = name
self.prefix = prefix
}
var fullName: {
return (prefix != nil ? prefix! + ” ” : “”) + name
}
}
var ncc1701 = Starship(name: “Enterprise”, prefix: “USS”)
// ncc1701.fullName is “USS Enterprise”

This class implements the fullName property requirement as a computed read-only property for a starship. Each Starship class instance stores a mandatory name and an optional prefix. The fullName property uses the prefix value if it exists, and prepends it to the beginning of name to create a full name for the starship.

Method Requirements
Protocols can require specific instance methods and type methods to be implemented by conforming types. These methods are written as part of the protocol’s definition in exactly the same way as for normal instance and type methods, but without curly braces or a method body. Variadic parameters are allowed, subject to the same rules as for normal methods. Default values, however, can’t be specified for method parameters within a protocol’s definition.
As with type property requirements, you always prefix type method requirements with the static keyword when they’re defined in a protocol. This is true even though type method requirements are prefixed with the class or static keyword when implemented by a class:

protocol SomeProtocol {
static func someTypeMethod()
}
The following example defines a protocol with a single instance method requirement:

protocol RandomNumberGenerator {
func random() ->
}
This protocol, RandomNumberGenerator, requires any conforming type to have an instance method called random, which returns a Double value whenever it’s called. Although it’s not specified as part of the protocol, it’s assumed that this value will be a number from 0.0 up to (but not including) 1.0.
The RandomNumberGenerator protocol doesn’t make any assumptions about how each random number will be generated—it simply requires the generator to provide a standard way to generate a new random number.
Here’s an implementation of a class that adopts and conforms to the RandomNumberGenerator protocol. This class implements a pseudorandom number generator algorithm known as a linear congruential generator:

class LinearCongruentialGenerator: {
var lastRandom = 42.0
let m = 139968.0
let a = 3877.0
let c = 29573.0
func random() -> {
lastRandom = ((lastRandom * a + c).truncatingRemainder(dividingBy:m))
return lastRandom / m
}
}
let generator = LinearCongruentialGenerator()
print(“Here’s a random number: \(generator.random())”)
// Prints “Here’s a random number: 0.37464991998171”
print(“And another one: \(generator.random())”)
// Prints “And another one: 0.729023776863283”

Mutating Method Requirements

It’s sometimes necessary for a method to modify (or mutate) the instance it belongs to. For instance methods on value types (that is, structures and enumerations) you place the mutating keyword before a method’s func keyword to indicate that the method is allowed to modify the instance it belongs to and any properties of that instance. This process is described in Modifying Value Types from Within Instance Methods.
If you define a protocol instance method requirement that is intended to mutate instances of any type that adopts the protocol, mark the method with the mutating keyword as part of the protocol’s definition. This enables structures and enumerations to adopt the protocol and satisfy that method requirement.If you mark a protocol instance method requirement as mutating, you don’t need to write the mutating keyword when writing an implementation of that method for a class. The mutating keyword is only used by structures and enumerations.

The example below defines a protocol called Togglable, which defines a single instance method requirement called toggle. As its name suggests, the toggle() method is intended to toggle or invert the state of any conforming type, typically by modifying a property of that type.The toggle() method is marked with the mutating keyword as part of the Togglable protocol definition, to indicate that the method is expected to mutate the state of a conforming instance when it’s called:

protocol Togglable {
mutating func toggle()
}
If you implement the Togglable protocol for a structure or enumeration, that structure or enumeration can conform to the protocol by providing an implementation of the toggle() method that is also marked as mutating.
The example below defines an enumeration called OnOffSwitch. This enumeration toggles between two states, indicated by the enumeration cases on and off. The enumeration’s toggle implementation is marked as mutating, to match the Togglable protocol’s requirements:

enum OnOffSwitch: {
case off, on
mutating func toggle() {
switch self {
case .off:
self = .on
case .on:
self = .off
}
}
}
var lightSwitch = OnOffSwitch.off
lightSwitch.toggle()
// lightSwitch is now equal to .on


Initializer RequirementsProtocols can require specific initializers to be implemented by conforming types. You write these initializers as part of the protocol’s definition in exactly the same way as for normal initializers, but without curly braces or an initializer body:protocol SomeProtocol {
init(someParameter: )
}

Class Implementations of Protocol Initializer Requirements
You can implement a protocol initializer requirement on a conforming class as either a designated initializer or a convenience initializer. In both cases, you must mark the initializer implementation with the required modifier:

class SomeClass: {
required init(someParameter: ) {
// initializer implementation goes here
}
}
The use of the required modifier ensures that you provide an explicit or inherited implementation of the initializer requirement on all subclasses of the conforming class, such that they also conform to the protocol.You don’t need to mark protocol initializer implementations with the required modifier on classes that are marked with the final modifier, because final classes can’t subclassed. For more on the final modifier, see Preventing Overrides.

If a subclass overrides a designated initializer from a superclass, and also implements a matching initializer requirement from a protocol, mark the initializer implementation with both the required and override modifiers:

protocol SomeProtocol {
init()
}class SomeSuperClass {
init() {
// initializer implementation goes here
}
}class SomeSubClass: , {
// “required” from SomeProtocol conformance; “override” from SomeSuperClass
required override init() {
// initializer implementation goes here
}
}

Failable Initializer Requirements

Protocols can define failable initializer requirements for conforming types, as defined in Failable Initializers.A failable initializer requirement can be satisfied by a failable or nonfailable initializer on a conforming type. A nonfailable initializer requirement can be satisfied by a nonfailable initializer or an implicitly unwrapped failable initializer.


Protocols as Type

Protocols don’t actually implement any functionality themselves. Nonetheless, any protocol you create will become a fully-fledged type for use in your code.
Because it’s a type, you can use a protocol in many places where other types are allowed, including:
As a parameter type or return type in a function, method, or initializer
As the type of a constant, variable, or property
As the type of items in an array, dictionary, or other container

Because protocols are types, begin their names with a capital letter (such as FullyNamed and RandomNumberGenerator) to match the names of other types in Swift (such as Int, String, and Double).Here’s an example of a protocol used as a type:

class Dice {
let sides:
let generator:
init(sides: , generator: ) {
self.sides = sides
self.generator = generator
}
func roll() -> {
return Int(generator.random() * Double(sides)) + 1
}
}

This example defines a new class called Dice, which represents an n-sided dice for use in a board game. Dice instances have an integer property called sides, which represents how many sides they have, and a property called generator, which provides a random number generator from which to create dice roll values.The generator property is of type RandomNumberGenerator. Therefore, you can set it to an instance of any type that adopts the RandomNumberGenerator protocol. Nothing else is required of the instance you assign to this property, except that the instance must adopt the RandomNumberGenerator protocol.Dice also has an initializer, to set up its initial state. This initializer has a parameter called generator, which is also of type RandomNumberGenerator. You can pass a value of any conforming type in to this parameter when initializing a new Dice instance.
Dice provides one instance method, roll, which returns an integer value between 1 and the number of sides on the dice. This method calls the generator’s random() method to create a new random number between 0.0 and 1.0, and uses this random number to create a dice roll value within the correct range. Because generator is known to adopt RandomNumberGenerator, it’s guaranteed to have a random() method to call.
Here’s how the Dice class can be used to create a six-sided dice with a LinearCongruentialGenerator instance as its random number generator:

var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
for _ in 1…5 {
print(“Random dice roll is \(d6.roll())”)
}
// Random dice roll is 3
// Random dice roll is 5
// Random dice roll is 4
// Random dice roll is 5
// Random dice roll is 4


Delegation

Delegation is a design pattern that enables a class or structure to hand off (or delegate) some of its responsibilities to an instance of another type. This design pattern is implemented by defining a protocol that encapsulates the delegated responsibilities, such that a conforming type (known as a delegate) is guaranteed to provide the functionality that has been delegated. Delegation can be used to respond to a particular action, or to retrieve data from an external source without needing to know the underlying type of that source.The example below defines two protocols for use with dice-based board games:

protocol DiceGame {
var dice: { get }
func play()
}
protocol DiceGameDelegate {
func gameDidStart(_ game: )
func game(_ game: , didStartNewTurnWithDiceRoll diceRoll: )
func gameDidEnd(_ game: )
}

The DiceGame protocol is a protocol that can be adopted by any game that involves dice. The DiceGameDelegate protocol can be adopted by any type to track the progress of a DiceGame.Here’s a version of the Snakes and Ladders game originally introduced in Control Flow. This version is adapted to use a Dice instance for its dice-rolls; to adopt the DiceGame protocol; and to notify a DiceGameDelegate about its progress:

class SnakesAndLadders: {
let finalSquare = 25
let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
var square = 0
var board: [] init() {
board = Array(repeating: 0, count: finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
}
var delegate: ?
func play() {
square = 0
delegate?.gameDidStart(self)
gameLoop: while square != finalSquare {
let diceRoll = dice.roll()
delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
switch square + diceRoll {
case finalSquare:
break gameLoop
case let newSquare where newSquare > finalSquare:
continue gameLoop
default:
square += diceRoll
square += board[square] }
}
delegate?.gameDidEnd(self)
}
}

This version of the game is wrapped up as a class called SnakesAndLadders, which adopts the DiceGame protocol. It provides a gettable dice property and a play() method in order to conform to the protocol. (The dice property is declared as a constant property because it doesn’t need to change after initialization, and the protocol only requires that it must be gettable.)The Snakes and Ladders game board setup takes place within the class’s init() initializer. All game logic is moved into the protocol’s play method, which uses the protocol’s required dice property to provide its dice roll values.
Note that the delegate property is defined as an optional DiceGameDelegate, because a delegate isn’t required in order to play the game. Because it’s of an optional type, the delegate property is automatically set to an initial value of nil. Thereafter, the game instantiator has the option to set the property to a suitable delegate.DiceGameDelegate provides three methods for tracking the progress of a game. These three methods have been incorporated into the game logic within the play() method above, and are called when a new game starts, a new turn begins, or the game ends.
Because the delegate property is an optional DiceGameDelegate, the play() method uses optional chaining each time it calls a method on the delegate. If the delegate property is nil, these delegate calls fail gracefully and without error. If the delegate property is non-nil, the delegate methods are called, and are passed the SnakesAndLadders instance as a parameter.
This next example shows a class called DiceGameTracker, which adopts the DiceGameDelegate protocol:

class DiceGameTracker: {
var numberOfTurns = 0
func gameDidStart(_ game: ) {
numberOfTurns = 0
if game is {
print(“Started a new game of Snakes and Ladders”)
}
print(“The game is using a \(game.dice.sides)-sided dice”)
}
func game(_ game: , didStartNewTurnWithDiceRoll diceRoll: ) {
numberOfTurns += 1
print(“Rolled a \(diceRoll)”)
}
func gameDidEnd(_ game: ) {
print(“The game lasted for \(numberOfTurns) turns”)
}
}

DiceGameTracker implements all three methods required by DiceGameDelegate. It uses these methods to keep track of the number of turns a game has taken. It resets a numberOfTurns property to zero when the game starts, increments it each time a new turn begins, and prints out the total number of turns once the game has ended.
The implementation of gameDidStart(_:) shown above uses the game parameter to print some introductory information about the game that is about to be played. The game parameter has a type of DiceGame, not SnakesAndLadders, and so gameDidStart(_:) can access and use only methods and properties that are implemented as part of the DiceGame protocol. However, the method is still able to use type casting to query the type of the underlying instance. In this example, it checks whether game is actually an instance of SnakesAndLadders behind the scenes, and prints an appropriate message if so.
The gameDidStart(_:) method also accesses the dice property of the passed game parameter. Because game is known to conform to the DiceGame protocol, it’s guaranteed to have a dice property, and so the gameDidStart(_:) method is able to access and print the dice’s sides property, regardless of what kind of game is being played.
Here’s how DiceGameTracker looks in action:

let tracker = DiceGameTracker()
let game = SnakesAndLadders()
game.delegate = tracker
game.play()
// Started a new game of Snakes and Ladders
// The game is using a 6-sided dice
// Rolled a 3
// Rolled a 5
// Rolled a 4
// Rolled a 5
// The game lasted for 4 turns


Adding Protocol Conformance with an Extension

You can extend an existing type to adopt and conform to a new protocol, even if you don’t have access to the source code for the existing type. Extensions can add new properties, methods, and subscripts to an existing type, and are therefore able to add any requirements that a protocol may demand. Existing instances of a type automatically adopt and conform to a protocol when that conformance is added to the instance’s type in an extension.

For example, this protocol, called TextRepresentable, can be implemented by any type that has a way to be represented as text. This might be a description of itself, or a text version of its current state:

protocol TextRepresentable {
var textualDescription: { get }
}
The Dice class from earlier can be extended to adopt and conform to TextRepresentable:

extension : {
var textualDescription: {
return “A \(sides)-sided dice”
}
}
This extension adopts the new protocol in exactly the same way as if Dice had provided it in its original implementation. The protocol name is provided after the type name, separated by a colon, and an implementation of all requirements of the protocol is provided within the extension’s curly braces.
Any Dice instance can now be treated as TextRepresentable:

let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
print(d12.textualDescription)
// Prints “A 12-sided dice”
Similarly, the SnakesAndLadders game class can be extended to adopt and conform to the TextRepresentable protocol:

extension : {
var textualDescription: {
return “A game of Snakes and Ladders with \(finalSquare) squares”
}
}
print(game.textualDescription)
// Prints “A game of Snakes and Ladders with 25 squares”

Declaring Protocol Adoption with an Extension

If a type already conforms to all of the requirements of a protocol, but has not yet stated that it adopts that protocol, you can make it adopt the protocol with an empty extension:

struct Hamster {
var name:
var textualDescription: {
return “A hamster named \(name)”
}
}
extension : {}
Instances of Hamster can now be used wherever TextRepresentable is the required type:

let simonTheHamster = Hamster(name: “Simon”)
let somethingTextRepresentable: = simonTheHamster
print(somethingTextRepresentable.textualDescription)
// Prints “A hamster named Simon”

Types don’t automatically adopt a protocol just by satisfying its requirements. They must always explicitly declare their adoption of the protocol.


Collections of Protocol Types

A protocol can be used as the type to be stored in a collection such as an array or a dictionary, as mentioned in Protocols as Types. This example creates an array of TextRepresentable things:

let things: [] = [game, d12, simonTheHamster]
It’s now possible to iterate over the items in the array, and print each item’s textual description:

for thing in things {
print(thing.textualDescription)
}
// A game of Snakes and Ladders with 25 squares
// A 12-sided dice
// A hamster named Simon

Note that the thing constant is of type TextRepresentable. It’s not of type Dice, or DiceGame, or Hamster, even if the actual instance behind the scenes is of one of those types. Nonetheless, because it’s of type TextRepresentable, and anything that is TextRepresentable is known to have a textualDescription property, it’s safe to access thing.textualDescription each time through the loop.

Protocol Inheritance

A protocol can inherit one or more other protocols and can add further requirements on top of the requirements it inherits. The syntax for protocol inheritance is similar to the syntax for class inheritance, but with the option to list multiple inherited protocols, separated by commas:

protocol InheritingProtocol: ,  {

    // protocol definition goes here

}

Here’s an example of a protocol that inherits the TextRepresentable protocol from above:

protocol PrettyTextRepresentable:  {

    var prettyTextualDescription:  { get }

}

This example defines a new protocol, PrettyTextRepresentable, which inherits from TextRepresentable. Anything that adopts PrettyTextRepresentable must satisfy all of the requirements enforced by TextRepresentable, plus the additional requirements enforced by PrettyTextRepresentable. In this example, PrettyTextRepresentable adds a single requirement to provide a gettable property called prettyTextualDescription that returns a String.

The SnakesAndLadders class can be extended to adopt and conform to PrettyTextRepresentable:

extension :  {

    var prettyTextualDescription:  {

        var output = textualDescription + “:\n”

        for index in 1finalSquare {

            switch board[index] {

            case let ladder where ladder > 0:

                output += “▲ “

            case let snake where snake < 0:

                output += “▼ “

            default:

                output += “○ “

            }

        }

        return output

    }

}

This extension states that it adopts the PrettyTextRepresentable protocol and provides an implementation of the prettyTextualDescription property for the SnakesAndLadders type. Anything that is PrettyTextRepresentable must also be TextRepresentable, and so the implementation of prettyTextualDescription starts by accessing the textualDescription property from the TextRepresentable protocol to begin an output string. It appends a colon and a line break, and uses this as the start of its pretty text representation. It then iterates through the array of board squares, and appends a geometric shape to represent the contents of each square:

If the square’s value is greater than 0, it’s the base of a ladder, and is represented by .

If the square’s value is less than 0, it’s the head of a snake, and is represented by .

Otherwise, the square’s value is 0, and it’s a “free” square, represented by .

The prettyTextualDescription property can now be used to print a pretty text description of any SnakesAndLadders instance:

print(game.prettyTextualDescription)

// A game of Snakes and Ladders with 25 squares:

// ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○

Class-Only Protocols

You can limit protocol adoption to class types (and not structures or enumerations) by adding the AnyObject protocol to a protocol’s inheritance list.

protocol SomeClassOnlyProtocol: ,  {

    // class-only protocol definition goes here

}

In the example above, SomeClassOnlyProtocol can only be adopted by class types. It’s a compile-time error to write a structure or enumeration definition that tries to adopt SomeClassOnlyProtocol.Use a class-only protocol when the behavior defined by that protocol’s requirements assumes or requires that a conforming type has reference semantics rather than value semantics. For more on reference and value semantics, see Structures and Enumerations Are Value Types and Classes Are Reference Types.

Protocol Composition

It can be useful to require a type to conform to multiple protocols at the same time. You can combine multiple protocols into a single requirement with a protocol composition. Protocol compositions behave as if you defined a temporary local protocol that has the combined requirements of all protocols in the composition. Protocol compositions don’t define any new protocol types.

Protocol compositions have the form SomeProtocol & AnotherProtocol. You can list as many protocols as you need, separating them with ampersands (&). In addition to its list of protocols, a protocol composition can also contain one class type, which you can use to specify a required superclass.Here’s an example that combines two protocols called Named and Aged into a single protocol composition requirement on a function parameter:

protocol Named {

    var name:  { get }

}

protocol Aged {

    var age:  { get }

}

struct Person: ,  {

    var name:

    var age:

}

func wishHappyBirthday(to celebrator:  & ) {

    print(“Happy birthday, \(celebrator.name), you’re \(celebrator.age)!”)

}

let birthdayPerson = Person(name: “Malcolm”, age: 21)

wishHappyBirthday(to: birthdayPerson)

// Prints “Happy birthday, Malcolm, you’re 21!”

In this example, the Named protocol has a single requirement for a gettable String property called name. The Aged protocol has a single requirement for a gettable Int property called age. Both protocols are adopted by a structure called Person.The example also defines a wishHappyBirthday(to:) function. The type of the celebrator parameter is Named & Aged, which means “any type that conforms to both the Named and Aged protocols.” It doesn’t matter which specific type is passed to the function, as long as it conforms to both of the required protocols.

The example then creates a new Person instance called birthdayPerson and passes this new instance to the wishHappyBirthday(to:) function. Because Person conforms to both protocols, this call is valid, and the wishHappyBirthday(to:) function can print its birthday greeting.Here’s an example that combines the Named protocol from the previous example with a Location class:

class Location {

    var latitude:

    var longitude:

    init(latitude: , longitude: ) {

        self.latitude = latitude

        self.longitude = longitude

    }

}

class City: ,  {

    var name:

    init(name: , latitude: , longitude: ) {

        self.name = name

        super.init(latitude: latitude, longitude: longitude)

    }

}

func beginConcert(in location:  & ) {

    print(“Hello, \(location.name)!”)

}

let seattle = City(name: “Seattle”, latitude: 47.6, longitude: -122.3)

beginConcert(in: seattle)

// Prints “Hello, Seattle!”

The beginConcert(in:) function takes a parameter of type Location & Named, which means “any type that’s a subclass of Location and that conforms to the Named protocol.” In this case, City satisfies both requirements.Passing birthdayPerson to the beginConcert(in:) function is invalid because Person isn’t a subclass of Location. Likewise, if you made a subclass of Location that didn’t conform to the Named protocol, calling beginConcert(in:) with an instance of that type is also invalid.

Checking for Protocol Conformance

You can use the is and as operators described in Type Casting to check for protocol conformance, and to cast to a specific protocol. Checking for and casting to a protocol follows exactly the same syntax as checking for and casting to a type:

The is operator returns true if an instance conforms to a protocol and returns false if it doesn’t.

The as? version of the downcast operator returns an optional value of the protocol’s type, and this value is nil if the instance doesn’t conform to that protocol.

The as! version of the downcast operator forces the downcast to the protocol type and triggers a runtime error if the downcast doesn’t succeed.

This example defines a protocol called HasArea, with a single property requirement of a gettable Double property called area:

protocol HasArea {

    var area:  { get }

}

Here are two classes, Circle and Country, both of which conform to the HasArea protocol:

class Circle:  {

    let pi = 3.1415927

    var radius:

    var area:  { return pi * radius * radius }

    init(radius: ) { self.radius = radius }

}

class Country:  {

    var area:

    init(area: ) { self.area = area }

}

The Circle class implements the area property requirement as a computed property, based on a stored radius property. The Country class implements the area requirement directly as a stored property. Both classes correctly conform to the HasArea protocol.

Here’s a class called Animal, which doesn’t conform to the HasArea protocol:

class Animal {

    var legs:

    init(legs: ) { self.legs = legs }

}

The Circle, Country and Animal classes don’t have a shared base class. Nonetheless, they’re all classes, and so instances of all three types can be used to initialize an array that stores values of type AnyObject:

let objects: [] = [

    Circle(radius: 2.0),

    Country(area: 243_610),

    Animal(legs: 4)

]

The objects array is initialized with an array literal containing a Circle instance with a radius of 2 units; a Country instance initialized with the surface area of the United Kingdom in square kilometers; and an Animal instance with four legs.

The objects array can now be iterated, and each object in the array can be checked to see if it conforms to the HasArea protocol:

for object in objects {

    if let objectWithArea = object as?  {

        print(“Area is \(objectWithArea.area))

    } else {

        print(“Something that doesn’t have an area”)

    }

}

// Area is 12.5663708

// Area is 243610.0

// Something that doesn’t have an area

Whenever an object in the array conforms to the HasArea protocol, the optional value returned by the as? operator is unwrapped with optional binding into a constant called objectWithArea. The objectWithArea constant is known to be of type HasArea, and so its area property can be accessed and printed in a type-safe way.Note that the underlying objects aren’t changed by the casting process. They continue to be a Circle, a Country and an Animal. However, at the point that they’re stored in the objectWithArea constant, they’re only known to be of type HasArea, and so only their area property can be accessed.

Optional Protocol Requirements

You can define optional requirements for protocols, These requirements don’t have to be implemented by types that conform to the protocol. Optional requirements are prefixed by the optional modifier as part of the protocol’s definition. Optional requirements are available so that you can write code that interoperates with Objective-C. Both the protocol and the optional requirement must be marked with the @objc attribute. Note that @objc protocols can be adopted only by classes that inherit from Objective-C classes or other @objc classes. They can’t be adopted by structures or enumerations.

When you use a method or property in an optional requirement, its type automatically becomes an optional. For example, a method of type (Int) -> String becomes ((Int) -> String)?. Note that the entire function type is wrapped in the optional, not the method’s return value.

An optional protocol requirement can be called with optional chaining, to account for the possibility that the requirement was not implemented by a type that conforms to the protocol. You check for an implementation of an optional method by writing a question mark after the name of the method when it’s called, such as someOptionalMethod?(someArgument). For information on optional chaining, see Optional Chaining.

The following example defines an integer-counting class called Counter, which uses an external data source to provide its increment amount. This data source is defined by the CounterDataSource protocol, which has two optional requirements:

@objc protocol CounterDataSource {
@objc optional func increment(forCount count: ) ->
@objc optional var fixedIncrement: { get }
}
The CounterDataSource protocol defines an optional method requirement called increment(forCount:) and an optional property requirement called fixedIncrement. These requirements define two different ways for data sources to provide an appropriate increment amount for a Counter instance.You can write a custom class that conforms to CounterDataSource without implementing either protocol requirement. They’re both optional, after all. Although technically allowed, this wouldn’t make for a very good data source.

The Counter class, defined below, has an optional dataSource property of type CounterDataSource?:

class Counter {
var count = 0
var dataSource: ?
func increment() {
if let amount = dataSource?.increment?(forCount: count) {
count += amount
} else if let amount = dataSource?.fixedIncrement {
count += amount
}
}
}

The Counter class stores its current value in a variable property called count. The Counter class also defines a method called increment, which increments the count property every time the method is called.
The increment() method first tries to retrieve an increment amount by looking for an implementation of the increment(forCount:) method on its data source. The increment() method uses optional chaining to try to call increment(forCount:), and passes the current count value as the method’s single argument.Note that two levels of optional chaining are at play here. First, it’s possible that dataSource may be nil, and so dataSource has a question mark after its name to indicate that increment(forCount:) should be called only if dataSource isn’t nil. Second, even if dataSource does exist, there’s no guarantee that it implements increment(forCount:), because it’s an optional requirement. Here, the possibility that increment(forCount:) might not be implemented is also handled by optional chaining. The call to increment(forCount:) happens only if increment(forCount:) exists—that is, if it isn’t nil. This is why increment(forCount:) is also written with a question mark after its name.
Because the call to increment(forCount:) can fail for either of these two reasons, the call returns an optional Int value. This is true even though increment(forCount:) is defined as returning a nonoptional Int value in the definition of CounterDataSource. Even though there are two optional chaining operations, one after another, the result is still wrapped in a single optional. For more information about using multiple optional chaining operations, see Linking Multiple Levels of Chaining.After calling increment(forCount:), the optional Int that it returns is unwrapped into a constant called amount, using optional binding. If the optional Int does contain a value—that is, if the delegate and method both exist, and the method returned a value—the unwrapped amount is added onto the stored count property, and incrementation is complete.
If it’s not possible to retrieve a value from the increment(forCount:) method—either because dataSource is nil, or because the data source doesn’t implement increment(forCount:)—then the increment() method tries to retrieve a value from the data source’s fixedIncrement property instead. The fixedIncrement property is also an optional requirement, so its value is an optional Int value, even though fixedIncrement is defined as a nonoptional Int property as part of the CounterDataSource protocol definition.
Here’s a simple CounterDataSource implementation where the data source returns a constant value of 3 every time it’s queried. It does this by implementing the optional fixedIncrement property requirement:

class ThreeSource: , {
let fixedIncrement = 3
}
You can use an instance of ThreeSource as the data source for a new Counter instance:

var counter = Counter()
counter.dataSource = ThreeSource()
for _ in 1…4 {
counter.increment()
print(counter.count)
}
// 3
// 6
// 9
// 12
The code above creates a new Counter instance; sets its data source to be a new ThreeSource instance; and calls the counter’s increment() method four times. As expected, the counter’s count property increases by three each time increment() is called.
Here’s a more complex data source called TowardsZeroSource, which makes a Counter instance count up or down towards zero from its current count value:

class TowardsZeroSource: ,  {

    func increment(forCount count: ) ->  {

        if count == 0 {

            return 0

        } else if count < 0 {

            return 1

        } else {

            return -1

        }

    }

}

The TowardsZeroSource class implements the optional increment(forCount:) method from the CounterDataSource protocol and uses the count argument value to work out which direction to count in. If count is already zero, the method returns 0 to indicate that no further counting should take place.

You can use an instance of TowardsZeroSource with the existing Counter instance to count from -4 to zero. Once the counter reaches zero, no more counting takes place:

counter.count = -4

counter.dataSource = TowardsZeroSource()

for _ in 15 {

    counter.increment()

    print(counter.count)

}

// -3

// -2

// -1

// 0

// 0

Protocol Extensions

Protocols can be extended to provide method and property implementations to conforming types. This allows you to define behavior on protocols themselves, rather than in each type’s individual conformance or in a global function.For example, the RandomNumberGenerator protocol can be extended to provide a randomBool() method, which uses the result of the required random() method to return a random Bool value:

extension  {

    func randomBool() ->  {

        return random() > 0.5

    }

}

By creating an extension on the protocol, all conforming types automatically gain this method implementation without any additional modification.

let generator = LinearCongruentialGenerator()

print(“Here’s a random number: \(generator.random()))

// Prints “Here’s a random number: 0.37464991998171”

print(“And here’s a random Boolean: \(generator.randomBool()))

// Prints “And here’s a random Boolean: true”


Providing Default Implementations

You can use protocol extensions to provide a default implementation to any method or computed property requirement of that protocol. If a conforming type provides its own implementation of a required method or property, that implementation will be used instead of the one provided by the extension.Protocol requirements with default implementations provided by extensions are distinct from optional protocol requirements. Although conforming types don’t have to provide their own implementation of either, requirements with default implementations can be called without optional chaining.

For example, the PrettyTextRepresentable protocol, which inherits the TextRepresentable protocol can provide a default implementation of its required prettyTextualDescription property to simply return the result of accessing the textualDescription property:

extension {
var prettyTextualDescription: {
return textualDescription
}
}


Adding Constraints to Protocol Extensions

When you define a protocol extension, you can specify constraints that conforming types must satisfy before the methods and properties of the extension are available. You write these constraints after the name of the protocol you’re extending using a generic where clause, as described in Generic Where Clauses.For instance, you can define an extension to the Collection protocol that applies to any collection whose elements conform to the TextRepresentable protocol from the example above.

extension where Iterator.Element: TextRepresentable {
var textualDescription: {
let itemsAsText = self.map { $0.textualDescription }
return “[” + itemsAsText.joined(separator: “, “) + “]”
}
}
The textualDescription property returns the textual description of the entire collection by concatenating the textual representation of each element in the collection into a comma-separated list, enclosed in brackets.
Consider the Hamster structure from before, which conforms to the TextRepresentable protocol, and an array of Hamster values:

let murrayTheHamster = Hamster(name: “Murray”)
let morganTheHamster = Hamster(name: “Morgan”)
let mauriceTheHamster = Hamster(name: “Maurice”)
let hamsters = [murrayTheHamster, morganTheHamster, mauriceTheHamster]
Because Array conforms to Collection and the array’s elements conform to the TextRepresentable protocol, the array can use the textualDescription property to get a textual representation of its contents:

print(hamsters.textualDescription)
// Prints “[A hamster named Murray, A hamster named Morgan, A hamster named Maurice]”

If a conforming type satisfies the requirements for multiple constrained extensions that provide implementations for the same method or property, Swift will use the implementation corresponding to the most specialized constraints.

‌‌

Generics

Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. You can write code that avoids duplication and expresses its intent in a clear, abstracted manner.Generics are one of the most powerful features of Swift, and much of the Swift standard library is built with generic code. In fact, you’ve been using generics throughout the Language Guide, even if you didn’t realize it. For example, Swift’s Array and Dictionary types are both generic collections. You can create an array that holds Int values, or an array that holds String values, or indeed an array for any other type that can be created in Swift. Similarly, you can create a dictionary to store values of any specified type, and there are no limitations on what that type can be.

The Problem That Generics Solve
Here’s a standard, nongeneric function called swapTwoInts(_:_:), which swaps two Int values:

func swapTwoInts(_ a: inout , _ b: inout ) {
let temporaryA = a
a = b
b = temporaryA
}
This function makes use of in-out parameters to swap the values of a and b.The swapTwoInts(_:_:) function swaps the original value of b into a, and the original value of a into b. You can call this function to swap the values in two Int variables:

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print(“someInt is now \(someInt), and anotherInt is now \(anotherInt)”)
// Prints “someInt is now 107, and anotherInt is now 3”

The swapTwoInts(_:_:) function is useful, but it can only be used with Int values. If you want to swap two String values, or two Double values, you have to write more functions, such as the swapTwoStrings(_:_:) and swapTwoDoubles(_:_:) functions shown below:

func swapTwoStrings(_ a: inout , _ b: inout ) {
let temporaryA = a
a = b
b = temporaryA
}

func swapTwoDoubles(_ a: inout , _ b: inout ) {
let temporaryA = a
a = b
b = temporaryA
}

You may have noticed that the bodies of the swapTwoInts(_:_:), swapTwoStrings(_:_:), and swapTwoDoubles(_:_:) functions are identical. The only difference is the type of the values that they accept (Int, String, and Double).It’s more useful, and considerably more flexible, to write a single function that swaps two values of any type. Generic code enables you to write such a function. (A generic version of these functions is defined below.)In all three functions, the types of a and b must be the same. If a and b aren’t of the same type, it isn’t possible to swap their values. Swift is a type-safe language, and doesn’t allow (for example) a variable of type String and a variable of type Double to swap values with each other. Attempting to do so results in a compile-time error.

‌Generic Functions

Generic functions can work with any type. Here’s a generic version of the swapTwoInts(_:_:) function from above, called swapTwoValues(_:_:):

func swapTwoValues(_ a: inout , _ b: inout ) {
let temporaryA = a
a = b
b = temporaryA
}
The body of the swapTwoValues(_:_:) function is identical to the body of the swapTwoInts(_:_:) function. However, the first line of swapTwoValues(_:_:) is slightly different from swapTwoInts(_:_:). Here’s how the first lines compare:

func swapTwoInts(_ a: inout , _ b: inout )
func swapTwoValues(_ a: inout , _ b: inout )

The generic version of the function uses a placeholder type name (called T, in this case) instead of an actual type name (such as Int, String, or Double). The placeholder type name doesn’t say anything about what T must be, but it does say that both a and b must be of the same type T, whatever T represents. The actual type to use in place of T is determined each time the swapTwoValues(_:_:) function is called.
The other difference between a generic function and a nongeneric function is that the generic function’s name (swapTwoValues(_:_:)) is followed by the placeholder type name (T) inside angle brackets (). The brackets tell Swift that T is a placeholder type name within the swapTwoValues(_:_:) function definition. Because T is a placeholder, Swift doesn’t look for an actual type called T.
The swapTwoValues(_:_:) function can now be called in the same way as swapTwoInts, except that it can be passed two values of any type, as long as both of those values are of the same type as each other. Each time swapTwoValues(_:_:) is called, the type to use for T is inferred from the types of values passed to the function.In the two examples below, T is inferred to be Int and String respectively:

var someInt = 3
var anotherInt = 107
swapTwoValues(&someInt, &anotherInt)
// someInt is now 107, and anotherInt is now 3

var someString = “hello”
var anotherString = “world”
swapTwoValues(&someString, &anotherString)
// someString is now “world”, and anotherString is now “hello”

The swapTwoValues(_:_:) function defined above is inspired by a generic function called swap, which is part of the Swift standard library, and is automatically made available for you to use in your apps. If you need the behavior of the swapTwoValues(_:_:) function in your own code, you can use Swift’s existing swap(_:_:) function rather than providing your own implementation.

‌Type Parameters

In the swapTwoValues(_:_:) example above, the placeholder type T is an example of a type parameter. Type parameters specify and name a placeholder type, and are written immediately after the function’s name, between a pair of matching angle brackets (such as ).
Once you specify a type parameter, you can use it to define the type of a function’s parameters (such as the a and b parameters of the swapTwoValues(_:_:) function), or as the function’s return type, or as a type annotation within the body of the function. In each case, the type parameter is replaced with an actual type whenever the function is called. (In the swapTwoValues(_:_:) example above, T was replaced with Int the first time the function was called, and was replaced with String the second time it was called.)You can provide more than one type parameter by writing multiple type parameter names within the angle brackets, separated by commas.

‌Naming Type Parameters

In most cases, type parameters have descriptive names, such as Key and Value in Dictionary<Key, Value> and Element in Array, which tells the reader about the relationship between the type parameter and the generic type or function it’s used in. However, when there isn’t a meaningful relationship between them, it’s traditional to name them using single letters such as T, U, and V, such as T in the swapTwoValues(_:_:) function above..

‌Generic Types

In addition to generic functions, Swift enables you to define your own generic types. These are custom classes, structures, and enumerations that can work with any type, in a similar way to Array and Dictionary.This section shows you how to write a generic collection type called Stack. A stack is an ordered set of values, similar to an array, but with a more restricted set of operations than Swift’s Array type. An array allows new items to be inserted and removed at any location in the array. A stack, however, allows new items to be appended only to the end of the collection (known as pushing a new value on to the stack). Similarly, a stack allows items to be removed only from the end of the collection (known as popping a value off the stack).

The concept of a stack is used by the UINavigationController class to model the view controllers in its navigation hierarchy. You call the UINavigationController class pushViewController(_:animated:) method to add (or push) a view controller on to the navigation stack, and its popViewControllerAnimated(_:) method to remove (or pop) a view controller from the navigation stack. A stack is a useful collection model whenever you need a strict “last in, first out” approach to managing a collection.

The illustration below shows the push and pop behavior for a stack:

1. There are currently three values on the stack.
2. A fourth value is pushed onto the top of the stack.
3. The stack now holds four values, with the most recent one at the top.
4 .The top item in the stack is popped.
5. After popping a value, the stack once again holds three values.

Here’s how to write a nongeneric version of a stack, in this case for a stack of Int values:

struct IntStack {
var items = [Int]()
mutating func push(_ item: ) {
items.append(item)
}
mutating func pop() -> {
return items.removeLast()
}
}
This structure uses an Array property called items to store the values in the stack. Stack provides two methods, push and pop, to push and pop values on and off the stack. These methods are marked as mutating, because they need to modify (or mutate) the structure’s items array.
The IntStack type shown above can only be used with Int values, however. It would be much more useful to define a generic Stack class, that can manage a stack of any type of value.Here’s a generic version of the same code:

struct Stack {
var items = [Element]()
mutating func push(_ item: ) {
items.append(item)
}
mutating func pop() -> {
return items.removeLast()
}
}
Note how the generic version of Stack is essentially the same as the nongeneric version, but with a type parameter called Element instead of an actual type of Int. This type parameter is written within a pair of angle brackets () immediately after the structure’s name.Element defines a placeholder name for a type to be provided later. This future type can be referred to as Element anywhere within the structure’s definition. In this case, Element is used as a placeholder in three places:
To create a property called items, which is initialized with an empty array of values of type Element
To specify that the push(_:) method has a single parameter called item, which must be of type Element
To specify that the value returned by the pop() method will be a value of type Element
Because it’s a generic type, Stack can be used to create a stack of any valid type in Swift, in a similar manner to Array and Dictionary.
You create a new Stack instance by writing the type to be stored in the stack within angle brackets. For example, to create a new stack of strings, you write Stack():

var stackOfStrings = Stack<>()
stackOfStrings.push(“uno”)
stackOfStrings.push(“dos”)
stackOfStrings.push(“tres”)
stackOfStrings.push(“cuatro”)
// the stack now contains 4 strings

Here’s how stackOfStrings looks after pushing these four values on to the stack:

Popping a value from the stack removes and returns the top value, “cuatro”:

let fromTheTop = stackOfStrings.pop()
// fromTheTop is equal to “cuatro”, and the stack now contains 3 strings

Here’s how the stack looks after popping its top value:


Extending a Generic Type

When you extend a generic type, you don’t provide a type parameter list as part of the extension’s definition. Instead, the type parameter list from the original type definition is available within the body of the extension, and the original type parameter names are used to refer to the type parameters from the original definition.
The following example extends the generic Stack type to add a read-only computed property called topItem, which returns the top item on the stack without popping it from the stack:

extension {
var topItem: ? {
return items.isEmpty ? nil : items[items.count – 1]
}
}
The topItem property returns an optional value of type Element. If the stack is empty, topItem returns nil; if the stack isn’t empty, topItem returns the final item in the items array.Note that this extension doesn’t define a type parameter list. Instead, the Stack type’s existing type parameter name, Element, is used within the extension to indicate the optional type of the topItem computed property.
The topItem computed property can now be used with any Stack instance to access and query its top item without removing it.

if let topItem = stackOfStrings.topItem {
print(“The top item on the stack is \(topItem).”)
}
// Prints “The top item on the stack is tres.”

Extensions of a generic type can also include requirements that instances of the extended type must satisfy in order to gain the new functionality, as discussed in Extensions with a Generic Where Clause below.

Type Constraints

The swapTwoValues(_:_:) function and the Stack type can work with any type. However, it’s sometimes useful to enforce certain type constraints on the types that can be used with generic functions and generic types. Type constraints specify that a type parameter must inherit from a specific class, or conform to a particular protocol or protocol composition.
For example, Swift’s Dictionary type places a limitation on the types that can be used as keys for a dictionary. As described in Dictionaries, the type of a dictionary’s keys must be hashable. That is, it must provide a way to make itself uniquely representable. Dictionary needs its keys to be hashable so that it can check whether it already contains a value for a particular key. Without this requirement, Dictionary could not tell whether it should insert or replace a value for a particular key, nor would it be able to find a value for a given key that is already in the dictionary.
This requirement is enforced by a type constraint on the key type for Dictionary, which specifies that the key type must conform to the Hashable protocol, a special protocol defined in the Swift standard library. All of Swift’s basic types (such as String, Int, Double, and Bool) are hashable by default.You can define your own type constraints when creating custom generic types, and these constraints provide much of the power of generic programming. Abstract concepts like Hashable characterize types in terms of their conceptual characteristics, rather than their concrete type.

Type Constraint Syntax

You write type constraints by placing a single class or protocol constraint after a type parameter’s name, separated by a colon, as part of the type parameter list. The basic syntax for type constraints on a generic function is shown below (although the syntax is the same for generic types):

func someFunction(someT: , someU: ) {
// function body goes here
}
The hypothetical function above has two type parameters. The first type parameter, T, has a type constraint that requires T to be a subclass of SomeClass. The second type parameter, U, has a type constraint that requires U to conform to the protocol SomeProtocol.

Type Constraints in Action

Here’s a nongeneric function called findIndex(ofString:in:), which is given a String value to find and an array of String values within which to find it. The findIndex(ofString:in:) function returns an optional Int value, which will be the index of the first matching string in the array if it’s found, or nil if the string can’t be found:

func findIndex(ofString valueToFind: , in array: []) -> ? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
The findIndex(ofString:in:) function can be used to find a string value in an array of strings:

let strings = [“cat”, “dog”, “llama”, “parakeet”, “terrapin”]
if let foundIndex = findIndex(ofString: “llama”, in: strings) {
print(“The index of llama is \(foundIndex)”)
}
// Prints “The index of llama is 2”

The principle of finding the index of a value in an array isn’t useful only for strings, however. You can write the same functionality as a generic function by replacing any mention of strings with values of some type T instead.
Here’s how you might expect a generic version of findIndex(ofString:in:), called findIndex(of:in:), to be written. Note that the return type of this function is still Int?, because the function returns an optional index number, not an optional value from the array. Be warned, though—this function doesn’t compile, for reasons explained after the example:

func findIndex(of valueToFind: , in array:[]) -> ? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
This function doesn’t compile as written above. The problem lies with the equality check, “if value == valueToFind”. Not every type in Swift can be compared with the equal to operator (==). If you create your own class or structure to represent a complex data model, for example, then the meaning of “equal to” for that class or structure isn’t something that Swift can guess for you. Because of this, it isn’t possible to guarantee that this code will work for every possible type T, and an appropriate error is reported when you try to compile the code.
All is not lost, however. The Swift standard library defines a protocol called Equatable, which requires any conforming type to implement the equal to operator (==) and the not equal to operator (!=) to compare any two values of that type. All of Swift’s standard types automatically support the Equatable protocol.Any type that is Equatable can be used safely with the findIndex(of:in:) function, because it’s guaranteed to support the equal to operator. To express this fact, you write a type constraint of Equatable as part of the type parameter’s definition when you define the function:

func findIndex(of valueToFind: , in array:[]) -> ? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
The single type parameter for findIndex(of:in:) is written as T: Equatable, which means “any type T that conforms to the Equatable protocol.”
The findIndex(of:in:) function now compiles successfully and can be used with any type that is Equatable, such as Double or String:

let doubleIndex = findIndex(of: 9.3, in: [3.14159, 0.1, 0.25])
// doubleIndex is an optional Int with no value, because 9.3 isn’t in the array
let stringIndex = findIndex(of: “Andrea”, in: [“Mike”, “Malcolm”, “Andrea”])
// stringIndex is an optional Int containing a value of 2


Associated Types

When defining a protocol, it’s sometimes useful to declare one or more associated types as part of the protocol’s definition. An associated type gives a placeholder name to a type that is used as part of the protocol. The actual type to use for that associated type isn’t specified until the protocol is adopted. Associated types are specified with the associatedtype keyword.

‌Associated Types in Action

Here’s an example of a protocol called Container, which declares an associated type called Item:

protocol Container {
associatedtype Item
mutating func append(_ item: )
var count: { get }
subscript(i: ) -> { get }
}
The Container protocol defines three required capabilities that any container must provide:
It must be possible to add a new item to the container with an append(_:) method.
It must be possible to access a count of the items in the container through a count property that returns an Int value.
It must be possible to retrieve each item in the container with a subscript that takes an Int index value.
This protocol doesn’t specify how the items in the container should be stored or what type they’re allowed to be. The protocol only specifies the three bits of functionality that any type must provide in order to be considered a Container. A conforming type can provide additional functionality, as long as it satisfies these three requirements.
Any type that conforms to the Container protocol must be able to specify the type of values it stores. Specifically, it must ensure that only items of the right type are added to the container, and it must be clear about the type of the items returned by its subscript.To define these requirements, the Container protocol needs a way to refer to the type of the elements that a container will hold, without knowing what that type is for a specific container. The Container protocol needs to specify that any value passed to the append(_:) method must have the same type as the container’s element type, and that the value returned by the container’s subscript will be of the same type as the container’s element type.
To achieve this, the Container protocol declares an associated type called Item, written as associatedtype Item. The protocol doesn’t define what Item is—that information is left for any conforming type to provide. Nonetheless, the Item alias provides a way to refer to the type of the items in a Container, and to define a type for use with the append(_:) method and subscript, to ensure that the expected behavior of any Container is enforced.
Here’s a version of the nongeneric IntStack type from earlier, adapted to conform to the Container protocol:

struct IntStack: {
// original IntStack implementation
var items = [Int]()
mutating func push(_ item: ) {
items.append(item)
}
mutating func pop() -> {
return items.removeLast()
}
// conformance to the Container protocol
typealias Item =
mutating func append(_ item: ) {
self.push(item)
}
var count: {
return items.count
}
subscript(i: ) -> {
return items[i] }
}

The IntStack type implements all three of the Container protocol’s requirements, and in each case wraps part of the IntStack type’s existing functionality to satisfy these requirements. IntStack specifies that for this implementation of Container, the appropriate Item to use is a type of Int. The definition of typealias Item = Int turns the abstract type of Item into a concrete type of Int for this implementation of the Container protocol.Thanks to Swift’s type inference, you don’t actually need to declare a concrete Item of Int as part of the definition of IntStack. Because IntStack conforms to all of the requirements of the Container protocol, Swift can infer the appropriate Item to use, simply by looking at the type of the append(_:) method’s item parameter and the return type of the subscript. Indeed, if you delete the typealias Item = Int line from the code above, everything still works, because it’s clear what type should be used for Item.
You can also make the generic Stack type conform to the Container protocol:

struct Stack: {
// original Stack implementation
var items = [Element]()
mutating func push(_ item: ) {
items.append(item)
}
mutating func pop() -> {
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(_ item: ) {
self.push(item)
}
var count: {
return items.count
}
subscript(i: ) -> {
return items[i] }
}

This time, the type parameter Element is used as the type of the append(_:) method’s item parameter and the return type of the subscript. Swift can therefore infer that Element is the appropriate type to use as the Item for this particular container.

Extending an Existing Type to Specify an Associated Type

You can extend an existing type to add conformance to a protocol, as described in Adding Protocol Conformance with an Extension. This includes a protocol with an associated type.
Swift’s Array type already provides an append(_:) method, a count property, and a subscript with an Int index to retrieve its elements. These three capabilities match the requirements of the Container protocol. This means that you can extend Array to conform to the Container protocol simply by declaring that Array adopts the protocol. You do this with an empty extension, as described in Declaring Protocol Adoption with an Extension:

extension : {}

Array’s existing append(_:) method and subscript enable Swift to infer the appropriate type to use for Item, just as for the generic Stack type above. After defining this extension, you can use any Array as a Container.

Using Type Annotations to Constrain an Associated Type

You can add a type annotation to an associated type in a protocol, to require that conforming types satisfy the constraints described by the type annotation. For example, the following code defines a version of Container that requires the items in the container to be equatable.

protocol Container {
associatedtype Item:
mutating func append(_ item: )
var count: { get }
subscript(i: ) -> { get }
}
To conform to this version of Container, the container’s Item type has to conform to the Equatable protocol.

Generic Where Clauses

Type constraints, as described in Type Constraints, enable you to define requirements on the type parameters associated with a generic function, subscript, or type.It can also be useful to define requirements for associated types. You do this by defining a generic where clause. A generic where clause enables you to require that an associated type must conform to a certain protocol, or that certain type parameters and associated types must be the same. A generic where clause starts with the where keyword, followed by constraints for associated types or equality relationships between types and associated types. You write a generic where clause right before the opening curly brace of a type or function’s body.The example below defines a generic function called allItemsMatch, which checks to see if two Container instances contain the same items in the same order. The function returns a Boolean value of true if all items match and a value of false if they don’t.
The two containers to be checked don’t have to be the same type of container (although they can be), but they do have to hold the same type of items. This requirement is expressed through a combination of type constraints and a generic where clause:

func allItemsMatch
(_ someContainer: C1, _ anotherContainer: C2) -> Bool
where . == ., .: {

// Check that both containers contain the same number of items.
if someContainer.count != anotherContainer.count {
return false
}

// Check each pair of items to see if they’re equivalent.
for i in 0.. if someContainer[i] != anotherContainer[i] {
return false
}
}

// All items match, so return true.
return true
}

This function takes two arguments called someContainer and anotherContainer. The someContainer argument is of type C1, and the anotherContainer argument is of type C2. Both C1 and C2 are type parameters for two container types to be determined when the function is called.
The following requirements are placed on the function’s two type parameters:
C1 must conform to the Container protocol (written as C1: Container).
C2 must also conform to the Container protocol (written as C2: Container).
The Item for C1 must be the same as the Item for C2 (written as C1.Item == C2.Item).
The Item for C1 must conform to the Equatable protocol (written as C1.Item: Equatable).
The first and second requirements are defined in the function’s type parameter list, and the third and fourth requirements are defined in the function’s generic where clause.
These requirements mean:
someContainer is a container of type C1.
anotherContainer is a container of type C2.
someContainer and anotherContainer contain the same type of items.
The items in someContainer can be checked with the not equal operator (!=) to see if they’re different from each other.
The third and fourth requirements combine to mean that the items in anotherContainer can also be checked with the != operator, because they’re exactly the same type as the items in someContainer.
These requirements enable the allItemsMatch(_:_:) function to compare the two containers, even if they’re of a different container type.
The allItemsMatch(_:_:) function starts by checking that both containers contain the same number of items. If they contain a different number of items, there’s no way that they can match, and the function returns false.
After making this check, the function iterates over all of the items in someContainer with a for-in loop and the half-open range operator (..<). For each item, the function checks whether the item from someContainer isn’t equal to the corresponding item in anotherContainer. If the two items aren’t equal, then the two containers don’t match, and the function returns false.
If the loop finishes without finding a mismatch, the two containers match, and the function returns true.
Here’s how the allItemsMatch(_:_:) function looks in action:

var stackOfStrings = Stack<>()
stackOfStrings.push(“uno”)
stackOfStrings.push(“dos”)
stackOfStrings.push(“tres”)

var arrayOfStrings = [“uno”, “dos”, “tres”]

if allItemsMatch(stackOfStrings, arrayOfStrings) {
print(“All items match.”)
} else {
print(“Not all items match.”)
}
// Prints “All items match.”

The example above creates a Stack instance to store String values, and pushes three strings onto the stack. The example also creates an Array instance initialized with an array literal containing the same three strings as the stack. Even though the stack and the array are of a different type, they both conform to the Container protocol, and both contain the same type of values. You can therefore call the allItemsMatch(_:_:) function with these two containers as its arguments. In the example above, the allItemsMatch(_:_:) function correctly reports that all of the items in the two containers match.

Extensions with a Generic Where Clause

You can also use a generic where clause as part of an extension. The example below extends the generic Stack structure from the previous examples to add an isTop(_:) method.

extension where Element: Equatable {
func isTop(_ item: ) -> {
guard let topItem = items.last else {
return false
}
return topItem == item
}
}
This new isTop(_:) method first checks that the stack isn’t empty, and then compares the given item against the stack’s topmost item. If you tried to do this without a generic where clause, you would have a problem: The implementation of isTop(_:) uses the == operator, but the definition of Stack doesn’t require its items to be equatable, so using the == operator results in a compile-time error. Using a generic where clause lets you add a new requirement to the extension, so that the extension adds the isTop(_:) method only when the items in the stack are equatable.
Here’s how the isTop(_:) method looks in action:

if stackOfStrings.isTop(“tres”) {
print(“Top element is tres.”)
} else {
print(“Top element is something else.”)
}
// Prints “Top element is tres.”

If you try to call the isTop(_:) method on a stack whose elements aren’t equatable, you’ll get a compile-time error.

struct NotEquatable { }
var notEquatableStack = Stack<>()
let notEquatableValue = NotEquatable()
notEquatableStack.push(notEquatableValue)
notEquatableStack.isTop(notEquatableValue) // Error

You can use a generic where clause with extensions to a protocol. The example below extends the Container protocol from the previous examples to add a startsWith(_:) method.

extension where Item: Equatable {
func startsWith(_ item: ) -> {
return count >= 1 && self[0] == item
}
}
The startsWith(_:) method first makes sure that the container has at least one item, and then it checks whether the first item in the container matches the given item. This new startsWith(_:) method can be used with any type that conforms to the Container protocol, including the stacks and arrays used above, as long as the container’s items are equatable.

if [9, 9, 9].startsWith(42) {
print(“Starts with 42.”)
} else {
print(“Starts with something else.”)
}
// Prints “Starts with something else.”
The generic where clause in the example above requires Item to conform to a protocol, but you can also write a generic where clauses that require Item to be a specific type. For example:

extension where Item == Double {
func average() -> {
var sum = 0.0
for index in 0.. { get }

associatedtype Iterator: where . ==
func makeIterator() ->
}
The generic where clause on Iterator requires that the iterator must traverse over elements of the same item type as the container’s items, regardless of the iterator’s type. The makeIterator() function provides access to a container’s iterator.
For a protocol that inherits from another protocol, you add a constraint to an inherited associated type by including the generic where clause in the protocol declaration. For example, the following code declares a ComparableContainer protocol that requires Item to conform to Comparable:

protocol ComparableContainer: where : { }


Generic Subscripts

Subscripts can be generic, and they can include generic where clauses. You write the placeholder type name inside angle brackets after subscript, and you write a generic where clause right before the opening curly brace of the subscript’s body. For example:

extension {
subscript(indices: ) -> []
where .. == {
var result = [Item]()
for index in indices {
result.append(self[index])
}
return result
}
}
This extension to the Container protocol adds a subscript that takes a sequence of indices and returns an array containing the items at each given index. This generic subscript is constrained as follows:
The generic parameter Indices in angle brackets has to be a type that conforms to the Sequence protocol from the standard library.
The subscript takes a single parameter, indices, which is an instance of that Indices type.
The generic where clause requires that the iterator for the sequence must traverse over elements of type Int. This ensures that the indices in the sequence are the same type as the indices used for a container.
Taken together, these constraints mean that the value passed for the indices parameter is a sequence of integers.

This Is A Custom Widget

This Sliding Bar can be switched on or off in theme options, and can take any widget you throw at it or even fill it with your custom HTML Code. Its perfect for grabbing the attention of your viewers. Choose between 1, 2, 3 or 4 columns, set the background color, widget divider color, activate transparency, a top border or fully disable it on desktop and mobile.

This Is A Custom Widget

This Sliding Bar can be switched on or off in theme options, and can take any widget you throw at it or even fill it with your custom HTML Code. Its perfect for grabbing the attention of your viewers. Choose between 1, 2, 3 or 4 columns, set the background color, widget divider color, activate transparency, a top border or fully disable it on desktop and mobile.