## Generics

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 Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}

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 String, _ b: inout String) {
let temporaryA = a
a = b
b = temporaryA
}

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

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.)

## Generic Functions

func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}

1. `func swapTwoInts(_ a: inout Int, _ b: inout Int)`
2. `func swapTwoValues<T>(_ a: inout T, _ b: inout T)`

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.

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”

## 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 `<T>`).

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.

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<Element>`, 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`.

NOTE

Always give type parameters upper camel case names (such as `T` and `MyTypeParameter`

## 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`.

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: Int) {
items.append(item)
}
mutating func pop() -> Int {
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<Element> {
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}

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

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

## 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.

(예를 들어 아래 예시에서 Element가 type parameter 이며 이것이 extending하는 부분에서 접근가능하다는 이야기)

struct Stack<Element> {
}

extension Stack {

// Element가 extended 정의의 type parameter이므로 접근 가능
var topItem: Element? {
return items.isEmpty ? nil : items[items.count – 1]
}
}

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

## Type Constraints

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<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
// 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

type constaints의 사용 예시

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: String, in array: [String]) -> Int? {
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<T>(of valueToFind: T, in array:[T]) -> Int? {
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<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
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

참고 사항) protocol에서 generic을 사용해야 하는 경우는 위에서 사용한 방법들과는 다르다. <T>의 방법은 사용 불가능하고 associatedtype을 대신 사용한다. 그 이전에는 typealias를 이용했으나 deprecated되었다.

참고 사항)

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: Item)
var count: Int { get }
subscript(i: Int) -> Item { 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.(generic type은 protocol 에서 정의되는 것이 아니고 conform하는 부분에서 수행된다.) 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: Container {
// original IntStack implementation
var items = [Int]()
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}

// conformance to the Container protocol

// 아래에서 설명하겠지만 이렇게 명시적으로 하는 방법이 있지만 암묵적으로도가능하다.
typealias Item = Int

mutating func append(_ item: Int) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
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.

Moreover, `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`. (명시적으로    typealias Item = Int 이렇게 하지 않아도 암묵적으로 swift가 알맞은 type을 찾을수 있다.)

You can also make the generic `Stack` type conform to the `Container` protocol:

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

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 {

// Item 은 Equatable protocol을 conform하는 것이어야 한다.
associatedtype Item: Equatable
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}

To conform to this version of `Container`, the container’s `Item` type has to conform to the `Equatable` protocol.

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: Equatable
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}

To conform to this version of `Container`, the container’s `Item` type has to conform to the `Equatable` protocol.

Using a Protocol in Its Associated Type’s Constraints

## (이해 못했던 부분)

A protocol can appear as part of its own requirements. For example, here’s a protocol that refines the `Container` protocol, adding the requirement of a `suffix(_:)` method. The `suffix(_:)` method returns a given number of elements from the end of the container, storing them in an instance of the `Suffix` type.

protocol SuffixableContainer: Container {
associatedtype Suffix: SuffixableContainer where Suffix.Item == Item
func suffix(_ size: Int) -> Suffix
}

In this protocol, `Suffix` is an associated type, like the `Item` type in the `Container` example above. `Suffix` has two constraints: It must conform to the `SuffixableContainer` protocol (the protocol currently being defined), and its `Item` type must be the same as the container’s `Item` type. The constraint on `Item` is a generic `where`clause, which is discussed in Associated Types with a Generic Where Clause below.

Here’s an extension of the `Stack` type from earlier that adds conformance to the `SuffixableContainer`protocol:

extension Stack: SuffixableContainer {
func suffix(_ size: Int) -> Stack {
var result = Stack()
for index in (count-size)..<count {
result.append(self[index])
}
return result
}
// Inferred that Suffix is Stack.
}
var stackOfInts = Stack<Int>()
stackOfInts.append(10)
stackOfInts.append(20)
stackOfInts.append(30)
let suffix = stackOfInts.suffix(2)
// suffix contains 20 and 30

In the example above, the `Suffix` associated type for `Stack` is also `Stack`, so the suffix operation on `Stack`returns another `Stack`. Alternatively, a type that conforms to `SuffixableContainer` can have a `Suffix` type that’s different from itself—meaning the suffix operation can return a different type. For example, here’s an extension to the nongeneric `IntStack` type that adds `SuffixableContainer` conformance, using `Stack<Int>` as its suffix type instead of `IntStack`:

extension IntStack: SuffixableContainer {
func suffix(_ size: Int) -> Stack<Int> {
var result = Stack<Int>()
for index in (count-size)..<count {
result.append(self[index])
}
return result
}
// Inferred that Suffix is Stack<Int>.
}

## 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:

//

<C1: Container, C2: Container> 이부분

//

defining a generic where clause

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

// 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..<someContainer.count {
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<String>()
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.

// Element 는

Equatable protocol을 conform해야만 한다.

extension Stack where Element: Equatable {
func isTop(_ item: Element) -> Bool {

// 맨위 아이템이 있는지 확인
guard let topItem = items.last else {
return false
}
}
}

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<NotEquatable>()

// 임의로

Equatable 를 conform 하지않는 요소 만들기
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 Container where Item: Equatable {
func startsWith(_ item: Item) -> Bool {
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 Container where Item == Double {
func average() -> Double {
var sum = 0.0
for index in 0..<count {
sum += self[index]
}
return sum / Double(count)
}
}
print([1260.0, 1200.0, 98.6, 37.0].average())
// Prints “648.9”

This example adds an `average()` method to containers whose `Item` type is `Double`. It iterates over the items in the container to add them up, and divides by the container’s count to compute the average. It explicitly converts the count from `Int` to `Double` to be able to do floating-point division.

You can include multiple requirements in a generic `where` clause that is part of an extension, just like you can for a generic `where` clause that you write elsewhere. Separate each requirement in the list with a comma.

## Associated Types with a Generic Where Clause

You can include a generic `where` clause on an associated type. For example, suppose you want to make a version of `Container` that includes an iterator, like what the `Sequence` protocol uses in the standard library. Here’s how you write that:

protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }

associatedtype Iterator: IteratorProtocol where Iterator.Element == Item
func makeIterator() -> Iterator
}

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: Container where Item: Comparable { }

## 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 Container {
subscript<Indices: Sequence>(indices: Indices) -> [Item]
where Indices.Iterator.Element == Int {
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.

## Generics

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 Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}

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 String, _ b: inout String) {
let temporaryA = a
a = b
b = temporaryA
}

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

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.)

## Generic Functions

func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}

1. `func swapTwoInts(_ a: inout Int, _ b: inout Int)`
2. `func swapTwoValues<T>(_ a: inout T, _ b: inout T)`

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.

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”

## 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 `<T>`).

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.

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<Element>`, 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`.

NOTE

Always give type parameters upper camel case names (such as `T` and `MyTypeParameter`

## 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`.

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: Int) {
items.append(item)
}
mutating func pop() -> Int {
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<Element> {
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}

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

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

## 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.

(예를 들어 아래 예시에서 Element가 type parameter 이며 이것이 extending하는 부분에서 접근가능하다는 이야기)

struct Stack<Element> {
}

extension Stack {

// Element가 extended 정의의 type parameter이므로 접근 가능
var topItem: Element? {
return items.isEmpty ? nil : items[items.count – 1]
}
}

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

## Type Constraints

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<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
// 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

type constaints의 사용 예시

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: String, in array: [String]) -> Int? {
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<T>(of valueToFind: T, in array:[T]) -> Int? {
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<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
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

참고 사항) protocol에서 generic을 사용해야 하는 경우는 위에서 사용한 방법들과는 다르다. <T>의 방법은 사용 불가능하고 associatedtype을 대신 사용한다. 그 이전에는 typealias를 이용했으나 deprecated되었다.

참고 사항)

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: Item)
var count: Int { get }
subscript(i: Int) -> Item { 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.(generic type은 protocol 에서 정의되는 것이 아니고 conform하는 부분에서 수행된다.) 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: Container {
// original IntStack implementation
var items = [Int]()
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}

// conformance to the Container protocol

// 아래에서 설명하겠지만 이렇게 명시적으로 하는 방법이 있지만 암묵적으로도가능하다.
typealias Item = Int

mutating func append(_ item: Int) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
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.

Moreover, `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`. (명시적으로    typealias Item = Int 이렇게 하지 않아도 암묵적으로 swift가 알맞은 type을 찾을수 있다.)

You can also make the generic `Stack` type conform to the `Container` protocol:

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

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 {

// Item 은 Equatable protocol을 conform하는 것이어야 한다.
associatedtype Item: Equatable
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}

To conform to this version of `Container`, the container’s `Item` type has to conform to the `Equatable` protocol.

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: Equatable
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}

To conform to this version of `Container`, the container’s `Item` type has to conform to the `Equatable` protocol.

Using a Protocol in Its Associated Type’s Constraints

## (이해 못했던 부분)

A protocol can appear as part of its own requirements. For example, here’s a protocol that refines the `Container` protocol, adding the requirement of a `suffix(_:)` method. The `suffix(_:)` method returns a given number of elements from the end of the container, storing them in an instance of the `Suffix` type.

protocol SuffixableContainer: Container {
associatedtype Suffix: SuffixableContainer where Suffix.Item == Item
func suffix(_ size: Int) -> Suffix
}

In this protocol, `Suffix` is an associated type, like the `Item` type in the `Container` example above. `Suffix` has two constraints: It must conform to the `SuffixableContainer` protocol (the protocol currently being defined), and its `Item` type must be the same as the container’s `Item` type. The constraint on `Item` is a generic `where`clause, which is discussed in Associated Types with a Generic Where Clause below.

Here’s an extension of the `Stack` type from earlier that adds conformance to the `SuffixableContainer`protocol:

extension Stack: SuffixableContainer {
func suffix(_ size: Int) -> Stack {
var result = Stack()
for index in (count-size)..<count {
result.append(self[index])
}
return result
}
// Inferred that Suffix is Stack.
}
var stackOfInts = Stack<Int>()
stackOfInts.append(10)
stackOfInts.append(20)
stackOfInts.append(30)
let suffix = stackOfInts.suffix(2)
// suffix contains 20 and 30

In the example above, the `Suffix` associated type for `Stack` is also `Stack`, so the suffix operation on `Stack`returns another `Stack`. Alternatively, a type that conforms to `SuffixableContainer` can have a `Suffix` type that’s different from itself—meaning the suffix operation can return a different type. For example, here’s an extension to the nongeneric `IntStack` type that adds `SuffixableContainer` conformance, using `Stack<Int>` as its suffix type instead of `IntStack`:

extension IntStack: SuffixableContainer {
func suffix(_ size: Int) -> Stack<Int> {
var result = Stack<Int>()
for index in (count-size)..<count {
result.append(self[index])
}
return result
}
// Inferred that Suffix is Stack<Int>.
}

## 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:

//

<C1: Container, C2: Container> 이부분

//

defining a generic where clause

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

// 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..<someContainer.count {
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<String>()
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.

// Element 는

Equatable protocol을 conform해야만 한다.

extension Stack where Element: Equatable {
func isTop(_ item: Element) -> Bool {

// 맨위 아이템이 있는지 확인
guard let topItem = items.last else {
return false
}
}
}

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<NotEquatable>()

// 임의로

Equatable 를 conform 하지않는 요소 만들기
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 Container where Item: Equatable {
func startsWith(_ item: Item) -> Bool {
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 Container where Item == Double {
func average() -> Double {
var sum = 0.0
for index in 0..<count {
sum += self[index]
}
return sum / Double(count)
}
}
print([1260.0, 1200.0, 98.6, 37.0].average())
// Prints “648.9”

This example adds an `average()` method to containers whose `Item` type is `Double`. It iterates over the items in the container to add them up, and divides by the container’s count to compute the average. It explicitly converts the count from `Int` to `Double` to be able to do floating-point division.

You can include multiple requirements in a generic `where` clause that is part of an extension, just like you can for a generic `where` clause that you write elsewhere. Separate each requirement in the list with a comma.

## Associated Types with a Generic Where Clause

You can include a generic `where` clause on an associated type. For example, suppose you want to make a version of `Container` that includes an iterator, like what the `Sequence` protocol uses in the standard library. Here’s how you write that:

protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }

associatedtype Iterator: IteratorProtocol where Iterator.Element == Item
func makeIterator() -> Iterator
}

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: Container where Item: Comparable { }

## 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 Container {
subscript<Indices: Sequence>(indices: Indices) -> [Item]
where Indices.Iterator.Element == Int {
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.

tumblr #swift #protocol )

## Protocols

A protocol defines a blueprint of methods, properties, and other requirements. 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

define protocols

protocol SomeProtocol {
// protocol definition goes here
}

struct SomeStructure: FirstProtocol, AnotherProtocol {
// 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: SomeSuperclass, FirstProtocol, AnotherProtocol {
// 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: Int { get set }
var doesNotNeedToBeSettable: Int { 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(하부 implementing class , structure, enumeration에서 수행될때는 class, static 사용가능하다는 이야기):

protocol FullyNamed {
var fullName: String { get }
}

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

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

## Method Requirements

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 {

// type method
static func someTypeMethod()
}

protocol RandomNumberGenerator {
func random() -> Double
}

class LinearCongruentialGenerator: RandomNumberGenerator {
var lastRandom = 42.0
let m = 139968.0
let a = 3877.0
let c = 29573.0
func random() -> Double {
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.

NOTE

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.(class에서는 본래 mutating을 사용하지 않는다.)

protocol Togglable {
mutating func toggle()
}

enum OnOffSwitch: Togglable {
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 Requirements

Protocols 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: Int)
}

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: SomeProtocol {
required init(someParameter: Int) {
// 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.

NOTE

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: SomeSuperClass, SomeProtocol {
// “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 Types

protocol is 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

NOTE

Because protocols are types, begin their names with a capital letter

class Dice {
let sides: Int
let generator: RandomNumberGenerator
init(sides: Int, generator: RandomNumberGenerator) {
self.sides = sides
self.generator = generator
}
func roll() -> Int {
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.

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: Dice { get }
func play()
}
protocol DiceGameDelegate {
func gameDidStart(_ game: DiceGame)
func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
func gameDidEnd(_ game: DiceGame)
}

let finalSquare = 25
let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
var square = 0
var board: [Int]
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: DiceGameDelegate?
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)
}
}

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

let tracker = DiceGameTracker()
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. For more about extensions, see Extensions.

NOTE

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.

protocol TextRepresentable {
var textualDescription: String { get }
}

extension Dice: TextRepresentable {
var textualDescription: String {
return “A (sides)-sided dice”
}
}

let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
print(d12.textualDescription)
// Prints “A 12-sided dice”

var textualDescription: String {
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: String
var textualDescription: String {
return “A hamster named (name)”
}
}

extension Hamster: TextRepresentable {}

Instances of `Hamster` can now be used wherever `TextRepresentable` is the required type:

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

NOTE

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: [TextRepresentable] = [game, d12, simonTheHamster]

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`.

## 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: (class의 경우는 하나의 super class만을 inheriting할수있지만 protocol은 여러개의 protocol을 inherit 할수있다.)

protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
// protocol definition goes here
}

protocol PrettyTextRepresentable: TextRepresentable {
var prettyTextualDescription: String { 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`.

var prettyTextualDescription: String {
var output = textualDescription + “:n”
for index in 1…finalSquare {
switch board[index] {
output += “▲ ”
case let snake where snake < 0:
output += “▼ ”
default:
output += “○ ”
}
}
return output
}
}

print(game.prettyTextualDescription)
// A game of Snakes and Ladders with 25 squares:
// ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○

## Class-Only Protocols

(structure,enumeration에서는 conform하지 못하고 class에서만

conform할수 잇게 만드는 방법)

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: AnyObject, SomeInheritedProtocol {
// 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`.

NOTE

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

(두개이상의  protocol을 수행하는 어떤 타입을 표현한다.  예를 들어 a & b는 a와 b protocol을 conform하는 어떤 type 을 의미)

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.

protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
struct Person: Named, Aged {
var name: String
var age: Int
}
func wishHappyBirthday(to celebrator: Named & Aged) {
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.

class Location {
var latitude: Double
var longitude: Double
init(latitude: Double, longitude: Double) {
self.latitude = latitude
self.longitude = longitude
}
}
class City: Location, Named {
var name: String
init(name: String, latitude: Double, longitude: Double) {
self.name = name
super.init(latitude: latitude, longitude: longitude)
}
}
func beginConcert(in location: Location & Named) {
print(“Hello, (location.name)!”)
}
let seattle = City(name: “Seattle”, latitude: 47.6, longitude: -122.3)
beginConcert(in: seattle)
// Prints “Hello, Seattle!”

## 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.

protocol HasArea {
var area: Double { get }
}

class Circle: HasArea {
let pi = 3.1415927
}

class Country: HasArea {
var area: Double
init(area: Double) { self.area = area }
}

class Animal {
var legs: Int
init(legs: Int) { self.legs = legs }
}

let objects: [AnyObject] = [
Country(area: 243_610),
Animal(legs: 4)
]

for object in objects {
if let objectWithArea = object as? HasArea {
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

## Protocol Extensions

(protocol을 extension해서 이 protocol을 conform하는 모든 class,structure,enumeration이 특정 functions, properties를 기본적으로 가지게 하는 방법)

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.

extension RandomNumberGenerator {
func randomBool() -> Bool {
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.

NOTE

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.

## 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 Collection where Iterator.Element: TextRepresentable {
var textualDescription: String {
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]”

NOTE

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.

tumblr #swift #protocol )

## Protocols

A protocol defines a blueprint of methods, properties, and other requirements. 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

define protocols

protocol SomeProtocol {
// protocol definition goes here
}

struct SomeStructure: FirstProtocol, AnotherProtocol {
// 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: SomeSuperclass, FirstProtocol, AnotherProtocol {
// 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: Int { get set }
var doesNotNeedToBeSettable: Int { 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(하부 implementing class , structure, enumeration에서 수행될때는 class, static 사용가능하다는 이야기):

protocol FullyNamed {
var fullName: String { get }
}

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

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

## Method Requirements

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 {

// type method
static func someTypeMethod()
}

protocol RandomNumberGenerator {
func random() -> Double
}

class LinearCongruentialGenerator: RandomNumberGenerator {
var lastRandom = 42.0
let m = 139968.0
let a = 3877.0
let c = 29573.0
func random() -> Double {
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.

NOTE

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.(class에서는 본래 mutating을 사용하지 않는다.)

protocol Togglable {
mutating func toggle()
}

enum OnOffSwitch: Togglable {
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 Requirements

Protocols 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: Int)
}

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: SomeProtocol {
required init(someParameter: Int) {
// 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.

NOTE

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: SomeSuperClass, SomeProtocol {
// “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 Types

protocol is 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

NOTE

Because protocols are types, begin their names with a capital letter

class Dice {
let sides: Int
let generator: RandomNumberGenerator
init(sides: Int, generator: RandomNumberGenerator) {
self.sides = sides
self.generator = generator
}
func roll() -> Int {
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.

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: Dice { get }
func play()
}
protocol DiceGameDelegate {
func gameDidStart(_ game: DiceGame)
func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
func gameDidEnd(_ game: DiceGame)
}

let finalSquare = 25
let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
var square = 0
var board: [Int]
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: DiceGameDelegate?
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)
}
}

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

let tracker = DiceGameTracker()
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. For more about extensions, see Extensions.

NOTE

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.

protocol TextRepresentable {
var textualDescription: String { get }
}

extension Dice: TextRepresentable {
var textualDescription: String {
return “A (sides)-sided dice”
}
}

let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
print(d12.textualDescription)
// Prints “A 12-sided dice”

var textualDescription: String {
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: String
var textualDescription: String {
return “A hamster named (name)”
}
}

extension Hamster: TextRepresentable {}

Instances of `Hamster` can now be used wherever `TextRepresentable` is the required type:

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

NOTE

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: [TextRepresentable] = [game, d12, simonTheHamster]

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`.

## 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: (class의 경우는 하나의 super class만을 inheriting할수있지만 protocol은 여러개의 protocol을 inherit 할수있다.)

protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
// protocol definition goes here
}

protocol PrettyTextRepresentable: TextRepresentable {
var prettyTextualDescription: String { 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`.

var prettyTextualDescription: String {
var output = textualDescription + “:n”
for index in 1…finalSquare {
switch board[index] {
output += “▲ ”
case let snake where snake < 0:
output += “▼ ”
default:
output += “○ ”
}
}
return output
}
}

print(game.prettyTextualDescription)
// A game of Snakes and Ladders with 25 squares:
// ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○

## Class-Only Protocols

(structure,enumeration에서는 conform하지 못하고 class에서만

conform할수 잇게 만드는 방법)

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: AnyObject, SomeInheritedProtocol {
// 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`.

NOTE

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

(두개이상의  protocol을 수행하는 어떤 타입을 표현한다.  예를 들어 a & b는 a와 b protocol을 conform하는 어떤 type 을 의미)

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.

protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
struct Person: Named, Aged {
var name: String
var age: Int
}
func wishHappyBirthday(to celebrator: Named & Aged) {
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.

class Location {
var latitude: Double
var longitude: Double
init(latitude: Double, longitude: Double) {
self.latitude = latitude
self.longitude = longitude
}
}
class City: Location, Named {
var name: String
init(name: String, latitude: Double, longitude: Double) {
self.name = name
super.init(latitude: latitude, longitude: longitude)
}
}
func beginConcert(in location: Location & Named) {
print(“Hello, (location.name)!”)
}
let seattle = City(name: “Seattle”, latitude: 47.6, longitude: -122.3)
beginConcert(in: seattle)
// Prints “Hello, Seattle!”

## 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.

protocol HasArea {
var area: Double { get }
}

class Circle: HasArea {
let pi = 3.1415927
}

class Country: HasArea {
var area: Double
init(area: Double) { self.area = area }
}

class Animal {
var legs: Int
init(legs: Int) { self.legs = legs }
}

let objects: [AnyObject] = [
Country(area: 243_610),
Animal(legs: 4)
]

for object in objects {
if let objectWithArea = object as? HasArea {
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

## Protocol Extensions

(protocol을 extension해서 이 protocol을 conform하는 모든 class,structure,enumeration이 특정 functions, properties를 기본적으로 가지게 하는 방법)

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.

extension RandomNumberGenerator {
func randomBool() -> Bool {
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.

NOTE

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.

## 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 Collection where Iterator.Element: TextRepresentable {
var textualDescription: String {
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]”

NOTE

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.

## Extensions

Extensions add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you do not have access to the original source code (known as retroactive modeling).

Extensions in Swift can:

• Add computed instance properties and computed type properties (stored property는 추가 할수 없다.)
• Define instance methods and type methods
• Provide new initializers
• Define subscripts
• Define and use new nested types
• Make an existing type conform to a protocol

In Swift, you can even extend a protocol to provide implementations of its requirements or add additional functionality that conforming types can take advantage of. For more details, see Protocol Extensions.

NOTE

Extensions can add new functionality to a type, but they cannot override existing functionality.

## Extension Syntax

Declare extensions with the `extension` keyword:

extension SomeType {
// new functionality to add to SomeType goes here
}

An extension can extend an existing type to make it adopt one or more protocols. To add protocol conformance, you write the protocol names the same way as you write them for a class or structure:

extension SomeType: SomeProtocol, AnotherProtocol {
// implementation of protocol requirements goes here
}

Adding protocol conformance in this way is described in Adding Protocol Conformance with an Extension.

An extension can be used to extend an existing generic type, as described in Extending a Generic Type. You can also extend a generic type to conditionally add functionality, as described in Extensions with a Generic Where Clause.

NOTE

If you define an extension to add new functionality to an existing type, the new functionality will be available on all existing instances of that type, even if they were created before the extension was defined

## Computed Properties

Extensions can add computed instance properties and computed type properties to existing types. This example adds five computed instance properties to Swift’s built-in `Double` type, to provide basic support for working with distance units:

extension Double {
var km: Double { return self * 1_000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
print(“One inch is (oneInch) meters”)
// Prints “One inch is 0.0254 meters”
let threeFeet = 3.ft
print(“Three feet is (threeFeet) meters”)
// Prints “Three feet is 0.914399970739201 meters”

let aMarathon = 42.km + 195.m
print(“A marathon is (aMarathon) meters long”)
// Prints “A marathon is 42195.0 meters long”

NOTE

Extensions can add new computed properties, but they cannot add stored properties, or add property observers to existing properties.

## Initializers

Extensions can add new initializers to existing types.

Extensions can add new convenience initializers to a class, but they cannot add new designated initializers or deinitializers to a class. Designated initializers and deinitializers must always be provided by the original class implementation.

NOTE

If you use an extension to add an initializer to a value type that provides default values for all of its stored properties and does not define any custom initializers, you can call the default initializer and memberwise initializer for that value type from within your extension’s initializer.

This would not be the case if you had written the initializer as part of the value type’s original implementation, as described in Initializer Delegation for Value Types.

struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
}

let defaultRect = Rect()
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
size: Size(width: 5.0, height: 5.0))

You can extend the `Rect` structure to provide an additional initializer that takes a specific center point and size:

extension Rect {
init(center: Point, size: Size) {
let originX = center.x – (size.width / 2)
let originY = center.y – (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}

This new initializer starts by calculating an appropriate origin point based on the provided `center` point and `size` value. The initializer then calls the structure’s automatic memberwise initializer `init(origin:size:)`, which stores the new origin and size values in the appropriate properties:

let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
size: Size(width: 3.0, height: 3.0))
// centerRect’s origin is (2.5, 2.5) and its size is (3.0, 3.0)

## Methods

Extensions can add new instance methods and type methods to existing types. The following example adds a new instance method called `repetitions` to the `Int` type:

extension Int {
func repetitions(task: () -> Void) {

// 0과 self사이의 정수를 인덱스로 순환

for _ in 0..<self {
}
}
}

3.repetitions {
print(“Hello!”)
}
// Hello!
// Hello!
// Hello!

Mutating Instance Methods

(참고사항 tumblr #swift #mutating #enum:

Structures and enumerations are value types. By default, the properties of a value type cannot be modified from within its instance methods.)

Instance methods added with an extension can also modify (or mutate) the instance itself. Structure and enumeration methods that modify `self` or its properties must mark the instance method as `mutating`, just like mutating methods from an original implementation.

extension Int {
mutating func square() {
self = self * self
}
}
var someInt = 3
someInt.square()
// someInt is now 9

## Subscripts

Extensions can add new subscripts to an existing type.

`123456789[0]` returns `9`

`123456789[1]` returns `8`

extension Int {
subscript(digitIndex: Int) -> Int {
var decimalBase = 1
for _ in 0..<digitIndex {
decimalBase *= 10
}
return (self / decimalBase) % 10
}
}
746381295[0]
// returns 5
746381295[1]
// returns 9
746381295[2]
// returns 2
746381295[8]
// returns 7

746381295[9]
// returns 0, as if you had requested:
0746381295[9]

## Nested Types

Extensions can add new nested types to existing classes, structures, and enumerations:

extension Int {
enum Kind {
case negative, zero, positive
}
var kind: Kind {
switch self {
case 0:
return .zero
case let x where x > 0:
return .positive
default:
return .negative
}
}
}

func printIntegerKinds(_ numbers: [Int]) {
for number in numbers {
switch number.kind {
case .negative:
print(“- ”, terminator: “”)
case .zero:
print(“0 ”, terminator: “”)
case .positive:
print(“+ ”, terminator: “”)
}
}
print(“”)
}
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
// Prints “+ + – 0 – 0 + ”

NOTE

`number.kind` is already known to be of type `Int.Kind`. Because of this, all of the `Int.Kind` case values can be written in shorthand form inside the `switch` statement, such as `.negative` rather than `Int.Kind.negative`

## Extensions

Extensions add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you do not have access to the original source code (known as retroactive modeling).

Extensions in Swift can:

• Add computed instance properties and computed type properties (stored property는 추가 할수 없다.)
• Define instance methods and type methods
• Provide new initializers
• Define subscripts
• Define and use new nested types
• Make an existing type conform to a protocol

In Swift, you can even extend a protocol to provide implementations of its requirements or add additional functionality that conforming types can take advantage of. For more details, see Protocol Extensions.

NOTE

Extensions can add new functionality to a type, but they cannot override existing functionality.

## Extension Syntax

Declare extensions with the `extension` keyword:

extension SomeType {
// new functionality to add to SomeType goes here
}

An extension can extend an existing type to make it adopt one or more protocols. To add protocol conformance, you write the protocol names the same way as you write them for a class or structure:

extension SomeType: SomeProtocol, AnotherProtocol {
// implementation of protocol requirements goes here
}

Adding protocol conformance in this way is described in Adding Protocol Conformance with an Extension.

An extension can be used to extend an existing generic type, as described in Extending a Generic Type. You can also extend a generic type to conditionally add functionality, as described in Extensions with a Generic Where Clause.

NOTE

If you define an extension to add new functionality to an existing type, the new functionality will be available on all existing instances of that type, even if they were created before the extension was defined

## Computed Properties

Extensions can add computed instance properties and computed type properties to existing types. This example adds five computed instance properties to Swift’s built-in `Double` type, to provide basic support for working with distance units:

extension Double {
var km: Double { return self * 1_000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
print(“One inch is (oneInch) meters”)
// Prints “One inch is 0.0254 meters”
let threeFeet = 3.ft
print(“Three feet is (threeFeet) meters”)
// Prints “Three feet is 0.914399970739201 meters”

let aMarathon = 42.km + 195.m
print(“A marathon is (aMarathon) meters long”)
// Prints “A marathon is 42195.0 meters long”

NOTE

Extensions can add new computed properties, but they cannot add stored properties, or add property observers to existing properties.

## Initializers

Extensions can add new initializers to existing types.

Extensions can add new convenience initializers to a class, but they cannot add new designated initializers or deinitializers to a class. Designated initializers and deinitializers must always be provided by the original class implementation.

NOTE

If you use an extension to add an initializer to a value type that provides default values for all of its stored properties and does not define any custom initializers, you can call the default initializer and memberwise initializer for that value type from within your extension’s initializer.

This would not be the case if you had written the initializer as part of the value type’s original implementation, as described in Initializer Delegation for Value Types.

struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
}

let defaultRect = Rect()
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
size: Size(width: 5.0, height: 5.0))

You can extend the `Rect` structure to provide an additional initializer that takes a specific center point and size:

extension Rect {
init(center: Point, size: Size) {
let originX = center.x – (size.width / 2)
let originY = center.y – (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}

This new initializer starts by calculating an appropriate origin point based on the provided `center` point and `size` value. The initializer then calls the structure’s automatic memberwise initializer `init(origin:size:)`, which stores the new origin and size values in the appropriate properties:

let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
size: Size(width: 3.0, height: 3.0))
// centerRect’s origin is (2.5, 2.5) and its size is (3.0, 3.0)

## Methods

Extensions can add new instance methods and type methods to existing types. The following example adds a new instance method called `repetitions` to the `Int` type:

extension Int {
func repetitions(task: () -> Void) {

// 0과 self사이의 정수를 인덱스로 순환

for _ in 0..<self {
}
}
}

3.repetitions {
print(“Hello!”)
}
// Hello!
// Hello!
// Hello!

Mutating Instance Methods

(참고사항 tumblr #swift #mutating #enum:

Structures and enumerations are value types. By default, the properties of a value type cannot be modified from within its instance methods.)

Instance methods added with an extension can also modify (or mutate) the instance itself. Structure and enumeration methods that modify `self` or its properties must mark the instance method as `mutating`, just like mutating methods from an original implementation.

extension Int {
mutating func square() {
self = self * self
}
}
var someInt = 3
someInt.square()
// someInt is now 9

## Subscripts

Extensions can add new subscripts to an existing type.

`123456789[0]` returns `9`

`123456789[1]` returns `8`

extension Int {
subscript(digitIndex: Int) -> Int {
var decimalBase = 1
for _ in 0..<digitIndex {
decimalBase *= 10
}
return (self / decimalBase) % 10
}
}
746381295[0]
// returns 5
746381295[1]
// returns 9
746381295[2]
// returns 2
746381295[8]
// returns 7

746381295[9]
// returns 0, as if you had requested:
0746381295[9]

## Nested Types

Extensions can add new nested types to existing classes, structures, and enumerations:

extension Int {
enum Kind {
case negative, zero, positive
}
var kind: Kind {
switch self {
case 0:
return .zero
case let x where x > 0:
return .positive
default:
return .negative
}
}
}

func printIntegerKinds(_ numbers: [Int]) {
for number in numbers {
switch number.kind {
case .negative:
print(“- ”, terminator: “”)
case .zero:
print(“0 ”, terminator: “”)
case .positive:
print(“+ ”, terminator: “”)
}
}
print(“”)
}
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
// Prints “+ + – 0 – 0 + ”

NOTE

`number.kind` is already known to be of type `Int.Kind`. Because of this, all of the `Int.Kind` case values can be written in shorthand form inside the `switch` statement, such as `.negative` rather than `Int.Kind.negative`

## Nested Types

To nest a type within another type, write its definition within the outer braces of the type it supports. Types can be nested to as many levels as are required.

Nested Types in Action

struct BlackjackCard {

// nested Suit enumeration
enum Suit: Character {
case spades = “♠”, hearts = “♡”, diamonds = “♢”, clubs = “♣”
}

// nested Rank enumeration
enum Rank: Int {
case two = 2, three, four, five, six, seven, eight, nine, ten
case jack, queen, king, ace
struct Values {
let first: Int, second: Int?
}
var values: Values {
switch self {
case .ace:
return Values(first: 1, second: 11)
case .jack, .queen, .king:
return Values(first: 10, second: nil)
default:
return Values(first: self.rawValue, second: nil)
}
}
}

// BlackjackCard properties and methods
let rank: Rank, suit: Suit
var description: String {
var output = “suit is (suit.rawValue),”
output += “ value is (rank.values.first)”
if let second = rank.values.second {
output += “ or (second)”
}
return output
}
}