【Swift 5.3】A Swift Tourから学ぶSwift【Xcode 12.3】

# はじめに
(参考①) [A Swift Tour]
(https://docs.swift.org/swift-book/GuidedTour/GuidedTour.html#//apple_ref/doc/uid/TP40014097-CH2-ID1)
↑本記事の主となるSwift公式サイトの記事。
(参考①') [A Swift Tour]
(https://rusutikaa.github.io/docs/index.html)
↑Swift.orgやApple Developer Documentationの日本語訳。
(参考②) [Swift実践入門 〜 今からはじめるiOSアプリ開発！ 基本文法を押さえて、簡単な電卓を作ってみよう]
(https://eh-career.com/engineerhub/entry/2017/05/25/110000)
↑Swift 5.3に拘らない人向け。
(参考③) [【Swift入門】オプショナル型を理解しよう]
(https://fukatsu.tech/optional-swift)
↑Optional型について理解したい方向け。
(参考④) [Swiftのオプショナル型の使いこなし]
(https://thinkit.co.jp/article/13489)
↑Optional型を扱う際の注意点を詳しく知りたい方向け。
(参考⑤) [When to use guard let rather than if let]
(https://www.hackingwithswift.com/quick-start/understanding-swift/when-to-use-guard-let-rather-than-if-let)
↑guard-let構文の使い所について知りたい方向け。(英語記事)
(参考⑥) [Optional Chaining]
(https://docs.swift.org/swift-book/LanguageGuide/OptionalChaining.html)
↑オプショナルチェイニングを解説するSwift.orgの公式ページ。(英語記事)
(参考⑦) [Swift Standard Library(GitHub)]
(https://github.com/apple/swift/tree/main/stdlib/public/core)
↑GitHubで公開されているSwiftの標準ライブラリ。(英語)
(参考⑧) [[JavaScript]　猿でもわかるクロージャ超入門　まとめ]
(http://dqn.sakusakutto.jp/2009/01/javascript_5.html)
↑クロージャについて理解を深めたい方向け。(JavaScriptで記述)
(参考⑨) [イメージで理解するSwiftの高階関数（filter, map, reduce, compactMap, flatMap）]
(https://qiita.com/shtnkgm/items/eaad3c6ab368463de8e3)
↑高階関数について理解を深めたい方向け。
(参考⑩) [[Swift]flatMap・compactMapの挙動はソースコードを読んで理解しよう〜型情報と実装から難関メソッドを突破する〜]
(https://qiita.com/crea/items/b065425bde990cbd1c82)
↑flatMap・compactMapの内部処理を理解したい方向け。
(参考⑪) [mapとflatMapという便利メソッドを理解する]
(https://qiita.com/shimesaba/items/1a89cb5600454f91cc67)
↑flatMapについて理解したい初心者の方向け。
(参考⑫) [Swift Language - ジェネリックス]
(https://sodocumentation.net/ja/swift/topic/774/%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AA%E3%83%83%E3%82%AF%E3%82%B9)
↑Swiftにおけるジェネリクスを理解したい方向け。
(参考⑬) [[Swift] rethrowsを少し整理してみた]
(https://dev.classmethod.jp/articles/swift-about-rethrows/)
↑rethrowについて理解したい方向け。
(参考⑭) [Swiftで値型と参照型の違いを理解する]
(https://qiita.com/koher/items/bcdbf6578b6edd1f9e0c)
↑値型と参照型の違いについて理解したい方向け。(@koher さんの記事は特におすすめ)
(参考⑮) [Swiftにおけるclassとstructの使い分け]
(https://cockscomb.hatenablog.com/entry/choosing-between-classes-and-structures)
↑データ・メソッドをまとめる「クラス」と「構造体」の使い分け方を知りたい方向け。
(参考⑯) [【Swift】クラスの継承とプロトコルの準拠の使い分け]
(https://qiita.com/Howasuto/items/9c84739a210b5a684d80)
↑クラスとプロトコルの違いを詳しく知りたい方向け。

# A Swift Tour
## "Hello, world!"
どの言語を学ぶにしても、最初に必ず作成・実行するプログラムがあります。
`"Hello, world!"`と画面に表示させるだけのプログラムです。
`Swift`では、以下のように記述します。

```swift
print("Hello, world!")
```

このコードから分かることは、`Swift`の簡潔性です。
`Swift`と同じ`オブジェクト指向言語(object-oriented language)`である`Java`では、以下のように記述します。

```java:java
class Hello {
　public static void main(String[] args) {
　　System.out.print("Hello, world!");
　}
}
```

`Java`は`"Hello, world!"`と表示させるだけのプログラムでさえ5行も要するのに対し、`Swift`は1行で済んでしまいます。`main()`関数も、行の末尾に`;(セミコロン)`も必要ありません。

## 単純変数(Simple Values)
### 変数・定数の宣言
`定数(constant)`を`宣言(declaration)`するときは`let`、`変数(variable)`を宣言するときは`var`を使います。
<編集メモ: mutable/immutableな変数(動的/静的),定数との違いにも触れる>

```swift:Hello,world!
var myVariable = 42  // 変数:myVariable = 42
myVariable = 50   // 変数:myVariable = 50(値の上書き)
let myConstant = 42  // 定数:myConstant = 42

print(myVariable, myConstant)  // 実行結果: 50 42
```

変数・定数には、`型(type)`という概念があります。
例えば、「614」は`数値(numeric type)`の中でも`整数(integer)`ですが、「614.0」のように`小数(float)`としても表現できます。一方で「"614"」と記述すれば、`文字列(string)`として認識されます。

### 型の分類
型の一覧は以下の通りです。<編集メモ: 図を分かりやすくする>

![スクリーンショット 2020-11-07 14.04.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/673880/ed2b6151-edcb-c0d1-15bf-3fde1e3de663.png)

型については、いきなり気にする必要はありません。
最初のうちは、整数は`int`で宣言し、実数は`double`で宣言する、などと決めて覚えてしまえば良いと思います。

### Swiftの特徴: 型推論(type inference)と型変換
`Swift`のコンパイラは`初期化子(initializer)`から型を推論(infer)することができます。上のコードも、型を`定義(definition)`していないのに変数を宣言することができています。
もちろん、次のコードのように、型を`明示的(explicit)`に定義(=`型アノテーション`)することもできます。
型推論は便利ですが、**バグ**や**処理速度の低下**に繋がるため、**明示的に型を定義**するようにしましょう。

```swift:明示的な型定義
let implicitInteger = 70   // 暗示的(implicit)な型定義
let implicitDouble = 70.0  // 暗示的な型定義
let explicitDouble: Double = 70  //明示的な型定義

print(implicitInteger, implicitDouble, explicitDouble)
// 実行結果: 70 70.0 70.0
```

`Swift`では、型が`暗黙的(implicit)`に他の型に`変換(convert)`されることはありません。
そのため、以下のようなコードを記述するとエラーが出力されます。

```swift:error
let label = "The width is "
let width = 94
let widthLabel = label + width

print(widthLabel)
// 実行結果:
// error: binary operator '+' cannot be applied to operands of type 'String' and 'Int'
```

`String型(=文字列)`と`Int型(=整数)`を`+演算子`で連結することはできません。`Int型`を`String型`に変換してから連結する必要があります。
型変換は以下のようにして行います。

```swift:型変換
let label = "The width is "
let width = 94
let widthLabel = label + String(width)  // Int型widthをString型に変換

print(widthLabel)
// 実行結果: The width is 94
```

文字列に値を埋め込むのであれば、型変換を行わずとも表示させる方法があります。
値を`()`で囲み、`()`の直前に`\(バックスラッシュ)`を記述するだけです。
なお、Macにおける`\`のショートカットキーは`⌥(option) と ¥`になります。

```swift:文字列への値の埋め込み
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."

print(appleSummary)
print(fruitSummary)
// 実行結果:
// I have 3 apples.
// I have 8 pieces of fruit.
```

### 複数行にわたる文字列の記述
複数行にわたる文字列を記述したい場合は、`"""(ダブルクォテーション)`で囲いましょう。
なお、可読性を向上させるために`Space`や`Tab`を入力した場合は、出力結果にも`Space`や`Tab`が含まれている状態になります。`""`で囲っているため、`Space`や`Tab`も一つの文字列として扱われています。
可読性は落ちますが、出力結果に含みたくない場合は左づめで記述するようにしましょう。

```swift:複数行にわたる文字列の記述
let quotation = """
　　I said "I have \(apples) apples."
　　And then I said "I have \(apples + oranges) pieces of fruit."
"""

print(quotation)
// 実行結果:
// 　　I said "I have 3 apples."
// 　　And then I said "I have 8 pieces of fruit."
```

### 配列と辞書
`配列(array)`や`辞書(dictionary; 連想配列)`を生成するには、`[]`でインデックスやキーを囲みましょう。
それぞれの`構成要素(component)`は`,(コンマ)`で`列挙(enumerate)`します。

```swift:配列・辞書の生成
//配列の生成
var shoppingList = ["catfish", "water", "tulips",]   // 型推論
shoppingList += [bread]   // 構成要素の追加(append)
shoppingList[1] = "bottle of water"   // 構成要素の更新

var wishList: [String] = ["salmon", "soda", "violet",]  // 型アノテーション

print(shoppingList[1])
print(shoppingList[3])
print(wishList[0])
// 実行結果:
// bottle of water
// bread
// salmon

//辞書の生成
var occupations = [   // 型推論
　　"Malcolm": "Captain",
　　"Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"  // キー"Jayne"の追加
occupations["Kaylee"] = "Engineer"  // キー"Kaylee"の更新

var currency: [String: String] = [  // 型アノテーション
　　"JPN": "yen",
　　"USA": "dollar",
]

print(occupations["Jayne"]!)
print(occupations["Kaylee"]!)
print(currency["USA"]!)
// 実行結果:
// Public Relations
// Engineer
// dollar
```

`配列`のインデックスに基づいた構成要素の出力は`print(配列変数名[インデックス])`と記述したのに対して、`辞書`のキーに基づいた値の出力は`print(辞書名["キー"]!)`のように、末尾に`!`を付加して記述しています。その理由は後述します。

### Swiftの特徴: 「Optional型」の存在
`配列`と`辞書`の大きな違いは、**存在しないインデックスの`参照(refer)`**のされ方です。
以下に、存在しない構成要素を出力するように仕組まれた`配列`と`辞書`のプログラムを記します。その実行結果に注目してください。

```swift:配列と辞書のエラー出力の違い
var errArray = [0, 1, 2,]
print(errArray[3])  // 存在しない構成要素の出力
// 実行結果:
// Fatal error: Index out of range

var errDictionary = [
　　"zero": 0,
　　"one": 1,
　　"two": 2,
]
print(errDictionary["two"])   // 存在する構成要素の出力
print(errDictionary["three"])  // 存在しない構成要素の出力
// 実行結果:
// Optional(2)  # 戻り値をunwrapするよう求められる
// nil  # 戻り値をunwrapするよう求められる
```

`配列`は、存在しないインデックスを出力しようとすると`実行時エラー(runtime error)`を出力します。この場合の戻り値は`nil`ではありません。`nil`**が格納される箱すら用意されていない**のです。
一方で、`辞書`は`Optional型(=nilへの参照を認める)`の値を出力します。**箱は用意されており、`nil`が格納**されています。

`辞書`は、**存在しないキーによる値の参照**が行われる可能性があるため、`Optional型`で値を返すように定義されています。しかし、`print()`関数は`引数(argument)`として`非Optional型(=nilへの参照を認めない)`の変数しか認めていないため、`print()`関数の引数の末尾に`!`を記述し、`Optional型 → 非Optional型の型変換(unwrap)`を行うようにします。
この型変換は、`Optinal型変数`の値が`nil`であっても`非Optional型`に変換を行うため、`強制アンラップ(forced-unwrap)`と呼ばれています。

ただし、`print(errDictionary["three"]?)`と記述して`アンラップ`してしまうと、値が`nil`であるにもかかわらず**nilを許容しない**ため、以下のような**実行時エラーが出力**されてしまいます。

```swift:nilの値をアンラップしようとしたときの出力エラー
Fatal error: Unexpectedly found nil while unwrapping an Optional value
```

### Optional型導入のメリットと使い方
`Swift`では基本的に、値は`Optional型`で返されます。理由は簡単で、`Optional型`を導入し、**文法的エラーを対象行数と共に返す**仕様にすることで、バグの原因となりうる箇所(=`Optional型変数`を含む行)を容易に特定できるようになります。

一方で、`print()`関数のように**`Optinal型`を認めていない関数**は数多く存在します。`Optional型`のメリットを採用しながら`処理(procedure)`を実現する方法として`オプショナルバインディング(Optinal Binding)`や`オプショナルチェイニング(Optional Chaining)`、`Nil結合演算子(nil-coalescing operator)`などがあります。いずれの方法も、`Optinal型変数`の中身を参照しながら処理を進めていきます。
`A Swift Tour`では、以下のように紹介されています。

#### オプショナルバインディング
```swift:if-let構文
var optionalName: String? = "John Appleseed"
var greeting = "Hello"   // 初期化として、挨拶は"Hello"と返すことにしておく

if let name = optionalName {   // ただし、名前のある人(optionalName != nil)が挨拶してきた場合は
    greeting = "Hello, \(name)"  // "Hello, (名前)"で返すようにする
}

print(greeting)
// 出力結果:
// Hello, John Appleseed
```

`if-let`構文によって、**`Optional型`の値が`nil`でない場合の処理**を実現しています。値が`nil`か`nilでない`かで条件分岐を行うため、変数の宣言時に`?`を型の後ろに付け、`Optional型`であることを明示的に定義しましょう。`if-let`構文では、`Optional<String>型`変数である`optionalName`を暗黙的に`アンラップ`しています。

`if-let`構文の代わりに`if`文を使う場合は、以下のように記述します。

```swift:if文で書くオプショナルバインディング
var optName: String? = "John Appleseed"
var ifGreeting = "Hi" // 初期化として、挨拶は"Hi"と返すことにしておく

if optName != nil {   // 変数optNameがnilでない場合は
　　let ifName = optName!  // 変数optNameを強制アンラップし、
　　ifGreeting = "Hi, \(ifName)"  // "Hi, (名前)"で返すようにする
}

print(ifGreeting)
// 実行結果:
// Hi, John Appleseed
```

条件処理節で`let name = optionalName!`のように`強制アンラップ`する必要があるため、使用する際は`if-let`構文で記述するようにしましょう。

##### if-let構文とguard-let構文

また`if-let`構文と似た処理として`guard-let`構文があります。`guard-let`構文では、`Optional型`変数が`nil`の場合の処理節の中に、`return`・`break`・`throw`など、**関数から抜け出す(=`スコープ(scope)`を抜ける)処理**が含まれていないと実行時エラーを吐くため、コーディングする際の安全性を向上させます。

```swift:guard-let構文
func checkNil(name: String?) {
　　guard let yourName = name else {  // 名前のない(name = nil)場合は
　　　　print("No name.")   // "No name."と返すようにして
　　　　return   // 関数checkNil()から抜ける
　　}
　　print("You are \(yourName).")  // 名前のある(name != nil)場合の処理
}

checkNil(name: nil)
// 実行結果: No name.
checkNil(name: "Jack")
// 実行結果: You are Jack.
```

`if-let`構文は**`Optional型変数`が`nil`でない場合に`アンラップ`を行う**ことを目的としているのに対し、`guard-let`構文は**`Optional型変数`が`nil`であるかどうかを確認**することを目的としています。そのため、`guard-let`構文は処理の冒頭に置かれ、**`nil判定(nil-check)`として機能**させるのが一般的です。
なお、`guard-let`構文を使用する際は、`guard let <変数の参照> else`のように、**末尾に`else`を記述**するのを忘れないようにしましょう。

#### オプショナルチェイニング

`オプショナルチェイニング`の説明に入る前に、以下のサンプルプログラムを見てみましょう。

```swift:強制アンラップ(!)
// 共通
class Residence {
　　var numOfRooms = 1
}

class Person {
　　var residence: Residence?
}

let john = Person()

// 強制アンラップ
let roomCount = john.residence!.numOfRooms

print(roomCount)
// 実行結果:
// Fatal error: Unexpectedly found nil while unwrapping an Optional value:
```

`class (クラス名)`で宣言している`クラス(class)`とは、`データ(data)`とデータを処理する`メソッド(method)`を枠組みとした`オブジェクト(object)`です。

上記プログラムでは、冒頭に2つのクラス`Residence`・`Person`を宣言しています。

クラス`Residence`の`クラス宣言(class declaration)`では、クラス`Residence`の実体(`インスタンス(instance)`)を構成する`フィールド(field)`の`numOfRooms`を生成し、Int型の整数「1」を`参照(refer)`するようにしています。

クラス`Person`のクラス宣言では、クラス`Person`のフィールド`residence`を生成し、これはクラス`Residence`の`クラス型変数(class type variable)`であると宣言しています。

また、`let`文でクラス`Person`のクラス型変数(定数)`john`を生成し、`= Person()`で**クラス`Person`のインスタンスを参照**するようにしています。

そして、ややこしい表現ですが、定数`roomCount`を生成(`let roomCount`)し、クラス型変数`john`のフィールド`john.residence`が参照するべきクラス`Residence`のフィールド`john.residence.numOfRooms`を参照させています。

ここで、クラス型変数`john`を構成するフィールド`residence`を強制アンラップした結果、`john.residence = nil`というエラーが表示されました。

これは、`let john = Person()`でクラス`Person`のクラス型変数`john`がクラス`Person`のインスタンス(を構成するフィールド`residence`)を参照できるようにしているのに対し、クラス`Person`の`クラス宣言(class declaration)`では、`デフォルトコンストラクタ(default constructor)`によってクラス`Residence`のクラス型変数`residence`が生成されただけで、`residence`が参照するものは宣言されていません。
クラス型変数`residence`の箱は生成されていますが、箱`residence`が参照すべきデータ`numOfRooms`が宣言されていないため、`residence`の値が`nil`となっているのです。

上のプログラムでは、**値が`nil`の`john.residence`を強制アンラップ**しているため、実行時エラーが出力されました。
このエラーを解決するには、以下のように記述を加えて**`residence`がクラス`Residence`のインスタンス(を構成するフィールド`numOfRooms`)を参照**できるように明示します。

```swift:実行時エラーの解決
class Person {
　　var residence: Residence? = Residence()  // Residenceのインスタンスへの参照
}

class Residence {
　　var numOfRooms = 1
}

let john = Person()

let roomCount = john.residence!.numOfRooms

print(roomCount)
// 実行結果: 1
```

なお、`()`は、厳密にはインスタンスを表すものではなく、`コンストラクタ(constructor)`の`呼び出し(call)`であることにも触れておきます。`()`によってクラスのコンストラクタを呼び出すことで、コンストラクタによってインスタンスを参照できるようになるのです。

`オプショナルチェイニング`は`強制アンラップ(!)`と似ていますが、実行結果が異なります。

```swift:オプショナルチェイニング(?)
// 共通
class Residence {
　　var numOfRooms = 1
}

class Person {
　　var residence: Residence?
}

let john = Person()
// オプショナルチェイニング
if let roomCount = john.residence?.numOfRooms {
　　print("John's residence has \(roomCount) room(s).")
} else {
　　print("Unable to retrieve the number of rooms.")
}
// 実行結果:
// Unable to retrieve the number of rooms.
```

`強制アンラップ`を行ったプログラムでは、`nil`の`プロパティ(property)`である`john.residence`を`非Optional型`に変換しようとしたため、実行時エラーが出力されていました。

一方で、`オプショナルチェイニング`を行ったプログラムでは、実行結果から分かるように、**正常に処理が実行**されているのです。
`オプショナルチェイニング`は、`Optional型`のプロパティやメソッド、`添字(subscript, index)`の後ろに`?`を付加することで、`?`を付加したプロパティ等の値が`nil`の場合は、その後ろのプロパティ(=`.numOfRooms`)を無視して`nil`を返します。
この性質を利用して、上のプログラムでは、`if-let-else`文で`roomCount`が`nil`である場合の処理として、文字列`"Unable to retrieve the number of rooms"`を表示するようにしています。

`オプショナルチェイニング`は、値が`nil`になりうる`メソッド`や`プロパティ`を扱うときに有効な処理方法です。上記プログラムのように、`オプショナルバインディング`と組み合わせて使うこともあります。

#### Nil結合演算子

```swift:??(Nil結合)演算子
let nickname: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi, \(nickname ?? fullName)"


print(informalGreeting)
// 出力結果:
// Hi, John Appleseed
```

`??(nil-coalescing operator; Nil結合演算子)`は`x ?? y`のように記述し、**x = nil**の場合はxを返し、**x != nil**の場合はyを返します。

`条件演算子(conditional operator)`でも同様の処理は可能です。以下のように記述します。

```swift:条件演算子
let nickname: String? = "Jack"
let fullName: String = "John Appleseed"
let conditionalGreeting = "Hi, \(nickname != nil ? nickname! : fullName)"

print(conditionalGreeting)
// 出力結果:
// Hi, Jack
```

`条件演算子`の場合、`x ? y : z`のように記述し、条件式`x`を評価した結果、`true`であれば`y`を返し、`false`であれば`z`を返します。今回のように`nickname`が`nil`でない、つまり条件式`x`が`true`である場合は、yにあたる`nickname`を返します。
一方で、最終的に`print()`関数の引数となる`conditionalGreeting`は`非Optional型`でなければならないため、その中身となる`""`で囲まれた文字列内の変数も`非Optional型`でなければなりません。そこで、`nickname`の末尾に`!`を付けることで`強制アンラップ`しています。

### オプショナル型(?)と暗黙的アンラップ型(!)
`Optional型変数`を扱う際に`?`や`!`を**型・変数の末尾に付加**しますが、この2つには違いがあります。
以下のプログラムで、両者の動作を比較してみましょう。

```swift:?と!
var num1: Int = 1   // 非Optional型
var optNum1: Int? = 4  // Optional型

print(num1 + optNum1)  // 非Optional型 + Optional型
// 実行結果:
// Error: Value of optional type 'Int?' must be unwrapped to a value of type 'Int'
print(num1 + optNum1!)  // 非Optional型 + 強制アンラップされたOptional型
// 実行結果: 5
print(optNum1)
// 実行結果: Optional(4)

var num2: Int = 3   // 非Optional型
var optNum2: Int! = 5  // 暗黙的アンラップ型

print(num2 + optNum2)
// 実行結果: 8
print(num2 + optNum2!)
// 実行結果: 8
print(optNum2)
// 実行結果: Optional(5)
```

`?`を付加して定義した`Optional型`変数は、関数の実行時に**`!`を付けて`強制アンラップ`**する必要があります。
一方で、`!`を付加して定義した`暗黙的アンラップ型(implicitly unwrapped optional)`変数は、`強制アンラップ`しなくても正常に実行されます。
上記プログラムの実行結果からも分かるように、`暗黙的アンラップ型`変数は基本的に`Optional型`として扱われますが、`非Optional型`変数と連結する際には**暗黙的にアンラップ**が行われます。

## 制御フロー(Control Flow)

`制御フロー`とは、プログラムの処理の`流れ(flow)`を指します。プログラミングでは、命令文を上から記述していきますが、実際に実行される処理にも以下の3つの種類が存在します。

1. 順次処理(sequence)
2. 分岐処理(selection): `if`, `switch`
3. 繰返し処理(iteration): `for`, `while`, `repeat`

プログラミングでは、基本的に上の命令文から下の命令文に向かって1行ずつ読み込む`順次処理`が行われますが、`if文(if statement)`や`switch文(switch statement)`を用いた`分岐処理`や、`for文(for statement)`や`while文(while statement)`、`repeat文(repeat statement)`を用いた`繰返し処理`を定義することもできます。

`A Swift Tour`では、以下のようなサンプルプログラムによって`分岐処理`・`繰返し処理`の宣言方法が紹介されています。

### 拡張for文(for-in文)

```swift:拡張for文
let individualScores: [Int] = [75, 43, 103, 87, 12]
var teamScore: Int = 0

for score in individualScores {
　　if score > 50 {
　　　　teamScore += 3
　　} else {
　　　　teamScore += 1
　　}

print(teamScore)
// 実行結果: 11
```

`拡張for文(enhanced for statement)`は、`for x in y`のように記述することで、`配列`や`辞書`のように、複数のデータやオブジェクトを格納する`コレクション`である`y`の各構成要素に対して`繰返し処理`を実行します。一般的に、`コレクション`は**複数のデータ**を格納するため、変数名は英単語の**複数形**で宣言します。そのため、各構成要素を表す変数`x`は、コレクション名の**単数形**で宣言します。

`拡張for文`を応用したサンプルプログラムは以下の通りです。

```swift:拡張for文の応用
let interestingNumbers: [String: [Int]] = [
　　"Prime": [2, 3, 5, 7, 11, 13,],
　　"Fibonacci": [1, 1, 2, 3, 5, 8,],
　　"Square": [1, 4, 9, 16, 25,],
]

var largest: Int = 0

for (kind, numbers) in interestingNumbers {
　　for number in numbers {
　　　　if number > largest {
　　　　　　largest = number
　　　　}
　　}
}

print(largest)
// 実行結果: 25
```

`for (x, y) in z`と記述し、キー`x`と値`y`で構成される`辞書`に対して`繰返し処理`を実現することもできます。

上記プログラムの`for (kind, numbers) in interestingNumbers`の部分に注目しましょう。この`拡張for文`は、様々なキー`kind`と値`numbers`を持つ`辞書`を1つずつ`走査(scan)`すると宣言しています。

それに続く`for number in numbers`の部分では、まずキー`Prime`に格納されている配列の全要素(=`numbers`)を1つずつ`走査`します。キー`Prime`内の全要素の走査を終えると、次はキー`Fibonacci`に格納されている配列の全要素の走査に移ります。同様の処理を繰り返すことで、すべての辞書の`値`を走査することができます。

### switch文

```swift:switch文
let vegetable = "red pepper"

switch vegetable {
case "celery":
　　print("Add some raisins and make ants on a log.")
case "cucumber", "watercress":
　　print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
　　print("Is it a spicy \(x)?")
default:
　　print("Everything tastes good in soup.")
}
```

`if文`は`条件式(conditional expression)`の判定結果に応じて**処理を2つに分岐**(`else-if文`によって`switch文`のような処理も可能)させるのに対し、`switch文`は`case`の後に続く`ラベル(label)`と照合(=`評価(evaluate)`)しながら**処理を複数に分岐**させます。なお、`Swift`では`switch文`の`スコープ`を抜け出すための`break文(break statement)`は不要です。

`switch vegetable`で定数`vegetable`の値を見るよう宣言し、`case x:`の部分で定数`vegetable`の値がラベル`x`である場合の処理を実現しています。

次に、`case let x where x.hasSuffix("pepper"):`の部分にも注目しましょう。
`switch s {case let x where y: z}`の構文では、`switch`に続く変数`s`が、条件式`y`を満たすような`ローカル変数(local variable; 局所変数)`である`x`と照合した結果、`true`であれば、`s = x`とし、処理`z`を実行します。

また、`String型変数`のメソッド`x.hasSuffix`は、引数で指定した`接尾辞(suffix)`と一致していれば`true`を、一致していなければ`false`を返すメソッドです。
`基本型`は、`パッケージ(package)`に`hasSuffix`のように型独自のメソッドを有しています。上記プログラムで用いられた`hasSuffix`は`Swift言語`と密接に関連する重要クラスの`クラスメソッド(class method)`であるため`静的インポート宣言(static import declaration)`は不要でした。ただし、中には`import文`で`静的インポート宣言`が必要なメソッドもあることに留意しましょう。

### while文とrepeat文

`while文`・`repeat文`は、与えた条件式を満たす間の`繰返し処理`を実現します。
`while文`は`条件式の評価 → 処理`の順に実行されるのに対し、`repeat文`は`処理 → 条件式の評価`の順で実行されます。
両者の違いを比較するサンプルプログラムは以下の通りです。

```swift:while文とrepeat文
// while文
var m: Int = 8

while m < 8 {
　　m *= 2
}

// repeat文
var n: Int = 8

repeat {
　　n *= 2
} while n < 8

print(m)   // 実行結果: 8
print(n)   // 実行結果: 16
```

`while文`は、`m < 8`を評価した結果が`false`だったため、**処理`m *= 2`を実行していません**。
一方で、`repeat文`は、**まずは処理`n *= 2`を実行**した後で`n < 8`を評価(この時点で`n = 16`)した結果が`false`だったため、繰返し処理を中断しています。

## 関数(function)とクロージャ(closure)

**複数の処理を一まとまりの集合として定義**したものを、`関数`や`サブルーチン(sub routine)`、`プロシージャ(procedure)`、`メソッド(method)`と呼びます。厳密には`返り値(return value)`を持つかどうかでこれらの`用語(technical term)`を使い分ける人もいますが、`A Swift Tour`においては`"function" `と説明されているため、本記事においても一貫して**`関数`**と表現します。

### 関数

`関数`を宣言したサンプルプログラムは以下の通りです。

```swift:関数の宣言と引数ラベルの変更
// 引数ラベルが必要な関数の宣言
func greet(person: String, day: String) -> String {
　　return "Hello \(person), today is \(day)."
}

var str1 = greet(person: "Bob", day: "Tuesday")

print(str1)
// 実行結果:
// Hello Bob, today is Tuesday.

// 引数ラベルが省略可能な関数の宣言
func greet(_ person: String, _ day: String) -> String {
　　return "Hello \(person), today is \(day)."
}

var str2 = greet("John", "Wednesday")

print(str2)
// 実行結果:
// Hello John, today is Wednesday.

// 任意の引数ラベルを付与した関数の宣言
func greet(name person: String, on day: String) -> String {
　　return "Hello \(person), today is \(day)."
}

var str3 = greet(name: "Tom", on: Friday)

print(str3)
// 実行結果:
// Hello Tom, today is Friday.
```

なお、関数`greet()`のように、`-> x`と「`返り値`がある」と定義した関数では、処理の中に必ず`return文(return statement)`を含む必要があります。

### クロージャ(closure; 無名関数, anonymous function)

上記プログラムでは、関数`greet()`と、`グローバル変数(global variable)`として関数の`呼び出し元(caller)`である`str1`、`str2`、`str3`の計4つを定義しています。これらの定義によって、他の場面で`greet`や`str`を関数・変数名として宣言すると、コード全体に紛らわしさが生まれ、可読性の低下に繋がるため使用しづらくなってしまいました。しかし、これでも関数`greet()`では`多重定義(overload)`を用いることで、関数で使用する名前の`領域(space)`を節約しています。

`可読性の高いコード(readable code)`にするためには、**`グローバル変数`の数を極力少なくする**必要があります。`グローバル変数`含む`グローバル名前空間(global namespace)`を節約するために、上記プログラムの変数`str`のように多用途な名前である場合や、用途が限られ`再利用(reuse)`が考えにくいような場合は、`クロージャ(無名関数)`を使用するようにしましょう。

上記プログラムを、`クロージャ`を用いて書き換えると以下のようになります。

```swift:クロージャの宣言とその利用
var greeting: (String, String) -> String = {(person: String, day: String) -> String in
　　return "Hello \(person), today is \(day)."
}

print(greeting("Bob","Tuesday"))
// 実行結果:
// Hello Bob, today is Tuesday.
```

関数`greet()`を`クロージャ`として`{(m: x) -> y in z}`と記述しました。この構文では、`x`型の`ローカル変数(local variable)`である`m`が処理`z`によって`y`型の値として返されます。

`クロージャ`を使うことで、`グローバル名前空間`の節約が可能になります。ただし、関数に名前を付けることは「**関数が行う処理をイメージできるようにする**」という大きな意味があります。**`クロージャ`の乱用**はかえって**可読性の低下に繋がる**ことにも留意しましょう。

### returnとprint

`クロージャ`を用いた上記のサンプルプログラムは、以下のように書き換えることもできます。

```swift:変数・関数greetingの書き換え
var greeting: (String, String) -> Void = {(person: String, day: String) -> Void in
　　print("Hello \(person), today is \(day).")
}

greeting("Bob", "Tuesday")
// 実行結果:
// Hello Bob, today is Tuesday.
```

`var greeting: (String, String) -> Void`の部分では、`(String, String) -> Void`型変数として`greeting`を宣言しています。これは、`パラメータ`として`(String, String)`型が入力され、`返り値`として`Void`型の値を返す`即時変数(IIFE; Immediately Invoked Function Expression)`として定義されています。

また、変数`greeting`はクロージャ`{}`を`参照`するよう定義しています。このように、変数と同様に扱われるような関数を`第一級関数(first-class function)`と呼びます。`Swift`は`第一級関数`の性質を有しています。

`Void`は`パラメータ`や`返り値`を持たないような型です。`print()`関数は、値を`出力(output)`するだけであり、その値は他の関数に`参照`されません。このサンプルプログラムでは`print()`で出力するだけなので、返り値の型として`Void型`を定義しています。

`print()`関数によって求める値を出力すればよいのに、なぜ今までのサンプルプログラムでは`return文`を介していたのでしょうか。
その理由は、値を`再利用`する可能性があるからです。先述したように、`print()`関数は**値を出力するだけ**であり、**その値を使って演算することはできない**のです。

ただ出力するだけでよいのであれば`print()`関数を使い、他の関数内で使用する可能性がある場合は`return文`で値を返し、その受け取り先の変数を`print()`関数によって値を出力するようにしましょう。

### 高階関数(higher order function)

`Swift`は、関数が変数と同様に扱われる`第一級関数`を有しています。
`高階関数`とは、`第一級関数`の性質のうち「**関数を引数や返り値にとることができるような関数**」を指しています。

本記事では`高階関数`のうち、多用途である以下の5つを取り上げて説明します。

#### map

`map`は、「**各構成要素への処理(=`マッピング(mapping)`)**」を実現します。サンプルプログラムは以下の通りです。

```swift:高階関数map
var numbers: [Int] = [20, 19, 7, 12, 4]

var triple: [Int] = numbers.map{(number: Int) -> Int in
　　var result: Int = 3 * number
　　// warning: Variable 'result' was never mutated
　　return result
}

// 引数の省略
var tripleAbbreviate: [Int] = numbers.map{
　　return 3 * $0
}

print(triple)
// 実行結果: [60, 51, 21, 36, 12]
print(tripleAbbreviate)
// 実行結果: [60, 51, 21, 36, 12]
```

`var triple: [Int] = numbers.map(..)`の部分では、高階関数`numbers.map()`の呼び出し元として`[Int]型`変数`triple`を定義しています。

`x.map{y}`の部分では、`Sequence型レシーバ(Sequence-Type receiver)`である`[Int]`型変数`numbers`の**各構成要素に対して、クロージャ`y`を実行**するよう宣言しています。

また、`型推論`によってクロージャ内の`引数`の`省略(abbreviate)`ができます。今回は引数が1つしかないため、その`第一引数(first argument)`を`$0`と記述していますが、引数が複数ある場合でも`$0`、`$1`、`$2`、のように記述することで、クロージャ内の引数の記述を省略することができます。

上記プログラムでは、`var result: Int = 3 * number`の部分で`warning`エラーが表示されます。`"Variable 'xxx' was never mutated."`とは、「**変数(の値)が`不変(immutable)`である**」という意味です。
変数`numbers`を`[20, 19, 7, 12, 4]`という`定数`の配列で定義している以上、各要素を3倍した値は不変であるため、その積`result`は`変数`として宣言(`var ..`)するのではなく、**`定数`として宣言(`let ..`)**しなさい、という`Xcode`からの忠告です。

`変数`の方が値の変更が可能という点で自由性が高いですが、**設定した値が後から変更**されてしまう危険性もあるため、不変の値をもつ数についてはなるべく`定数`として宣言するようにしましょう。

#### filter

`filter`は、「**条件を満たす構成要素の抽出**」を実現します。サンプルプログラムは以下の通りです。

```swift:高階関数filter
var words: [String] = ["blanket", "roof", "rail", "building", "sandstorm"]

let extract: [String] = words.filter({(word: String) -> Bool in
　　return word.hasPrefix("b")
})

// 引数の省略
let extractAbbreviate: [String] = words.filter({
　　return $0.hasPrefix("b")
})

print(extract)
// 実行結果: ["blanket", "building]
print(extractAbbreviate)
// 実行結果: ["blanket", "building]
```

`x.filter{y}`の部分では、`Sequence型レシーバ`である`x`の各構成要素を、抽出条件`y`と照合しながら`抽出(extract)`する処理を宣言しています。また、その抽出条件`y`を`$0.hasPrefix("b")`と定義しています。

`String型メソッド`である`$0.hasPrefix(z)`は、`[String]`型配列の各構成要素`$0`が、`接頭辞(prefix)`に引数`z`を持つような要素であれば`true`を返すメソッドです。

上記のことから、`words.filter{return $0.hasPrefix("b")}`の部分は、配列`words`の各構成要素`$0`のうち、接頭辞`b`を持つ(=`$0.hasPrefix("b")`が`true`である)要素を抽出した`[String]`型配列を指しているのが分かります。

#### reduce

`reduce`は「**各構成要素の集計**」を実現します。サンプルプログラムは以下の通りです。


```swift:高階関数reduce
var numbers: [Int] = [20, 19, 7, 12, 4]

let countUp: Int = numbers.reduce(0){(sum: Int, num: Int) -> Int in
　　return sum + num
}

// 引数の省略
let countUpAbbreviate: Int = numbers.reduce(0){
　　return $0 + $1
}

print(countUp)   // 実行結果: 62
print(countUpAbbreviate)  // 実行結果: 62
```

`x.reduce(y){m z n}`の部分では、`Sequence型レシーバ`である`x`の構成要素を`集計(aggregate)`する処理を宣言しています。その変換処理は、初期値を`y`として`m`に`代入(substitute)`した後、各構成要素の`n`に対して`演算子(operator)`である`z`で演算を行います。

引数を省略した場合の`演算(operation)`について、第一引数`$0`には、1回目の処理では**初期値**が、2回目以降の処理では**前回の処理終了時の結果**が代入されます。また、第二引数`$1`には、**前回処理で扱った構成要素の、次の構成要素**が代入されます。(意味が分からない方は[こちら](https://qiita.com/pkaTaka/items/93e6e6920946e86b0a1c)を参照してください)

今回の場合、初期値は`0`、演算子として`+`を用いているため、初期値`0`に対して1つ目の構成要素である`20`から最後の構成要素である`4`まで順番に、`加法(addition)`による処理が行われています。

#### compactMap

`compactMap`は「**各構成要素の処理および`nil`でない値の抽出**」を実現します。サンプルプログラムは以下の通りです。

```swift:高階関数compactMap
var numbers: [Int] = [20, 19, 7, 12, 4]

let lessThan10Triple: [Int] = numbers.compactMap{(number: Int) -> Int? in
　　return number < 10 ? 3 * number : nil
}

// 引数の省略
let lessThan10TripleAbbreviate: [Int] = numbers.compactMap{
　　return $0 < 10 ? 3 * $0 : nil
}

// compactMapの内部処理
let compMapInnerProcedure: [Int] = numbers.filter{ return $0 < 10 }.map{ return 3 * $0 }

print(lessThan10Triple)
// 実行結果: [21, 12]
print(lessThan10TripleAbbreviate)
// 実行結果: [21, 12]
print(compMapInnerProcedure)
// 実行結果: [21, 12]
```

`compactMap`は、**`.map`と`.filter`を一度に実行**するような処理を行うため、`compactMap`という名称になっています。

`x.compactMap{y}`の部分では、`Sequence型レシーバ`である`x`の各構成要素に対して、条件式`y`で**処理(`.map`)**および**`nil`でない値の抽出(`.filter{ $0 != nil }`)**を実行しています。

条件式`y`の部分では、`三項条件演算子(ternary operator)`である`?:`を用いて`x ? y : z`と記述し、条件式`x`が`true`であれば`y`を評価した値、`false`であれば`z`を評価した値を`生成(generate)`します。

今回の場合、各構成要素`$0`が条件式`$0 < 10`を満たしている(=`true`)場合は`3 * $0`、満たしていない(=`false`)場合は`nil`を返しています。
`compactMap`では、`マッピング`を実行する前に**`.filter{ $0 != nil }`が自動的に実行**され、`nil`の値は処理されません。

この性質を利用し、三項条件演算子`?:`を用いて、処理条件を満たさない構成要素には`nil`を参照させ、`nil`でない(=処理条件を満たす)構成要素にのみ処理が実行されるように設定しましょう。

#### flatMap

`flatMap`は「**多次元配列の`次元削減(dimensionality reduction; 平坦化, flat)`**」を実現します。サンプルプログラムは以下の通りです。

```swift:高階関数flatMap
var numbers: [[[Int]]] = [ [[1, 2], [3, 4]], [[5, 6], [7, 8]] ]

let reductDimension: [[Int]] = numbers.flatMap{(number: [[Int]]) -> [[Int]] in
　　return number
}

// 引数の省略
let reductDimensionAbbreviate: [[Int]] = numbers.flatMap{
　　return $0
}

// 1次元化
let oneDimensionAbbreviate: [Int] = numbers.flatMap{return $0}.flatMap{return $0}

print(reductDimension)
// 実行結果:
// [[1, 2], [3, 4], [5, 6], [7, 8]]
print(reductDimensionAbbreviate)
// 実行結果:
// [[1, 2], [3, 4], [5, 6], [7, 8]]
print(oneDimensionAbbreviate)
// 実行結果:
// [1, 2, 3, 4, 5, 6, 7, 8]
```

`x.flatMap{y}`の部分では、`n次元のSequence型レシーバ`である`x`の各構成要素を取り出して`(n-1)次元のSequence型変数`に格納しています。
そのため、**`n次元`配列を`1次元`配列にする**場合は、`.flatMap{return $0}`を**`(n-1)`回繋げて記述**することで`平坦化`することができます。

また、`compactMap`で自動的に実行される`.filter{ $0 != nil }`は、非推奨とされていますが`.flatMap{ $0 }`としても記述することができます。
この場合の`flatMap`は、平坦化する`flatMap`ではなく**nilを除外する`flatMap`**です。

`flatMap`は以下のように`多重定義`されています。

```swift:多重定義されたflatMap
extension Sequence {

　　// 平坦化のflatMap
　　public func flatMap<SegmentOfResult: Sequence>(
　　　　_ transform: (Self.Element) throws -> SegmentOfResult
　　) rethrows -> [SegmentOfResult.Element] where SegmentOfResult: Sequence {
　　　　var result: [SegmentOfResult.Element] = []

　　　　for element in self {
　　　　　　result.append(contentsOf: try transform(element))
　　　　}
　　return result
　　}

　　// nil除外のflatMap
　　public func flatMap<ElementOfResult>(
　　　　_ transform: (Self.Element) throws -> ElementOfResult?
　　) rethrows -> [ElementOfResult] {
　　　　return try _compactMap(transform)
　　}

} 
```

`extension Sequence{...}`の部分ではクラス`Sequence`の型の`拡張(extension)`を行っています。つまり、`flatMap`は**クラス`Sequence`の`クラスメソッド`として定義**されています。そのため、`Sequence型`でない変数に対しては`flatMap`を用いることはできません。
このように、**ユーザが定義した要件に応じて任意の型で動作可能な、柔軟で再利用が可能な関数**のことを`ジェネリクス関数(generics function; 総称関数, 汎用関数)`と呼びます。

##### flatMap(平坦化)の定義

`public func flatMap<SegmentOfResult: Sequence>`の部分では、`public`が付いていることから、`flatMap`関数は`パッケージ`とは無関係に利用できる`公開アクセス(public access)`であることが分かります。
また、将来的に値が入る領域を確保する`プレースホルダ(placeholder; 型パラメータ)`として`Sequence`クラスの型パラメータ`SegmentOfResult`を設定しています。

`(_ transform: (Element) throws -> SegmentOfResult)`の部分では、`Sequence型`変数の構成要素`(Self.Element)`を引数として`Sequence`型の値`SegmentOfResult`を返すクロージャ`transform`を省略可能なパラメータとしながら、クロージャ`transform`は、場合によってはエラーの種類を出力する`例外(exception)`を投げる(=`throw`)と宣言しています。

`(...) rethrows -> [SegmentOfResult.Element] where SegmentOfResult: Sequence {...}`の部分では、上記の部分で投げられた例外の`例外処理(exception handling)`を宣言しています。
クロージャ`transform`によって例外が投げられた場合、その`例外処理`はクロージャ`transform`で行うのではなく、クロージャ`transform`の呼び出し元である`flatMap`で行う(=`rethrow`)としています。
また、高階関数`flatMap`は最終的に`Sequence型`のクラス型変数`SegmentOfResult`の構成要素`SegmentOfResult.Element`で構成される(=`where ...`)配列`[SegmentOfResult.Element]`を返すと宣言しています。

次は、`flatMap`の内部処理`{}`に注目します。
`var result: [SegmentOfResult.Element] = []`の部分では、配列`[SegmentOfResult.Element]`に、空の配列[]を参照させることで`初期化`しています。

そして、`for element in self{result.append(contentsOf: try transform(element))}`の部分では、配列の中でも**`flatMap`自身の型(=`self`)**である`[SegmentOfResult.Element]型`配列の各構成要素を、配列に複数の値を追加する`append(contentsOf:)`メソッドを用いて、空の配列`[]`(=`result`)に次々と追加しています。この部分で、**`-1`次元の次元削減が処理**されています。
このとき、配列に値を追加する**`append(contentsOf: x)`の引数`x`は`配列`でなければならない**ため、メソッド`transform(element)`によって各構成要素を配列に変換しています。ただし、先述したようにメソッド`transform(element)`は場合によってはエラーを出力する可能性があるため、メソッドの宣言の直前に`try文(try statement)`を付加しています。

最終的に、`return result`で`-1`次元の`次元削減`が行われた(=`平坦化`された)`[SegmentOfResult.Element]`型の配列が`返却`されます。

##### flatMap(nil除外)の定義

外部処理については、平坦化の`flatMap`とほぼ同様の処理が行われています。その差異は、メソッド`transform()`は`Optional<ElementOfResult>`型である配列を経由しますが、**最終的に高階関数`compactMap`によって`[ElementOfResult]型`の配列が返却される**ことです。

内部処理`{return try _compactMap(transform)}`に注目すると、内部的に`filter{ return $0 != nil`が行われる`compactMap`が用いられているのが分かります。
この部分で、**`nil`の値は配列から除外**されるのです。

## オブジェクトとクラス

`Swift`のような`オブジェクト指向プログラミング言語(OOPL; Object-Oriented Programming Language)`では、値を表す`データ(data)`と値を操作する`メソッド`を枠組みとした`オブジェクト`を中心に処理が行われます。
また、オブジェクト同士で同様の`データ`・`メソッド`を持つようなオブジェクトの概念を`クラス`と呼びます。クラスはあくまで`概念(scheme)`であり、クラスが持つ`データ`・`メソッド`の実体は`インスタンス(instance)`と呼ばれます。

クラスを宣言する以下のサンプルプログラムに注目しましょう。

```swift:イニシャライザを定義しないクラス宣言
class Shape {
　　var numberOfSides = 0

　　func simpleDescription() -> String {
　　　　return "A shape with \(numberOfSides) sides."
　　}
}
```

イニシャライザを定義するクラス`Shape`では、「図形の頂点の数」を値とする`プロパティ(property; 属性)`である`numberOfSides`を宣言し、`初期化子(initializer)`として`0`を参照させています。イニシャライザを使用しない場合、`nil安全(nil safe)`のために`初期化子`で`初期化(initialize)`する必要があります。
また、「図形の頂点の数」を出力する`メソッド(method)`を`simpleDescription`と宣言しています。

この時点では、クラス`Shape`の実体である`インスタンス`はまだ生成されていません。あくまで概念が宣言されただけの状態です。

```swift:インスタンス生成
var shape: Shape = Shape()

shape.numberOfSides = 7

var shapeDescription = shape.simpleDescription()

print(shapeDescription)
// 実行結果:
// A shape with 7 sides.
```

`var shape: Shape = Shape()`の部分では、クラス`Shape`で定義した`プロパティ`・`メソッド`を持つクラス型変数`shape`が、クラス`Shape`のインスタンス`Shape()`を参照するよう宣言しています。
`<クラス>()`は`既定イニシャライザ(default initializer)`と呼ばれ、イニシャライザが設定されていないクラスのインスタンスを生成します。ただし、**`イニシャライザ`を設定しない(=`既定イニシャライザ`を使用する)場合**は、**それぞれのインスタンスプロパティに`初期化子`が必要**です。

### イニシャライザと継承(inheritance)

既定イニシャライザを使用せず、イニシャライザをクラス宣言に組み込む場合のサンプルプログラムは以下の通りです。

`shape.numberOfSides = 7`の部分では、クラス型変数`shape`のプロパティ`shape.numberOfSides`に`Int型データ`である`7`を参照させています。

`var shapeDescription = shape.simpleDescription()`の部分では、クラス型変数`shape`のメソッド`shape.simpleDescription()`を参照し実行する変数`shapeDescription`を宣言しています。

```swift:イニシャライザを定義するクラス宣言
class NamedShape {
　　var numberOfSides: Int = 0
　　var name: String

　　// イニシャライザ
　　init(name: String) {
　　　　self.name = name
　　}

　　func simpleDescription() -> String {
　　　　return "A shape with \(numberOfSides) sides."
　　}
}
```

イニシャライザを定義するクラス`NamedShape`では、「図形の頂点の数」を値とする初期化済みプロパティ`numberOfSides`に加え、「図形の名前」を値とする未初期化のプロパティ`name`を宣言しています。
未初期化のプロパティ`name`は、`イニシャライザ`によって値が代入される必要があります。今回の場合、`指定イニシャライザ(designated initializer)`となる`init(name: String){ self.name = name }`で、`仮引数(parameter)`である`name`をインスタンスプロパティ`self.name`に代入し初期化しています。
定義されるクラス自身のプロパティを表す時は、`self`で自身のクラスを表現します。`self`というキーワードは、仮引数の`name`とクラス`Shape`が持つプロパティ`name`と区別するために用いられています。
また、この`self`は子クラス(`サブクラス`)を表すときにも使用され、親クラス(`スーパークラス`)を表す`super`と対照されます。

クラスには、`継承(inheritance)`という概念があります。動物の遺伝のように、親クラスの持つプロパティやメソッドを、子クラスが引き継ぎます。

クラスの継承を行うサンプルプログラムは以下の通りです。

```swift:サブクラスのクラス宣言とインスタンスの生成
// クラスNamedShapeの子クラスSquareのクラス宣言
class Square: NamedShape {
　　var sideLength: Double

　　// イニシャライザ
　　init(sideLength: Double, name: String) {
　　　　self.sideLength = sideLength
　　　　super.init(name: name)
　　　　numberOfSides = 4   // 'self.'キーワードの省略
　　}

　　func area() -> Double {
　　　　return sideLength * sideLength
　　}

　　override func simpleDescription() -> String {
　　　　return "A square with sides of length \(sideLength)."
　　}
}

// 子クラスSquareのインスタンス生成
let sampleSquare: Square = Square(sideLength: 5.2, name: "my sample square")

print(sampleSquare.area())
// 実行結果: 27.040000000000003
print(sampleSquare.simpleDescription())
// 実行結果:
A square with sides of length 5.2.
```

`class Square: NamedShape {...}`の部分では、クラス`NamedShape`を親クラスとする子クラス`Square`を定義しています。

`var sideLength: Double`の部分では、子クラス`Square`のプロパティとして、親クラス`NamedShape`が持っている`numberOfSides`・`name`に加えて、新たに`sideLength`を宣言しています。

`init(sideLength: Double, name: String) {...}`の部分では、子クラス`Square`のイニシャライザを定義しています。このイニシャライザでは、クラス`Square`が持つプロパティ`sideLength`・`name`・`numberOfSides`の初期化を行っています。

プロパティ`sideLength`については、子クラス`Square`で新たに追加したプロパティであり、仮引数をプロパティと同名の`selfLength`にしていますが、仮引数とプロパティを区別するために`self`をプロパティのレシーバとして初期化を行います。
一方で、プロパティ`name`は親クラス`NamedShape`のイニシャライザを使い回せるため、`super.init(name: name)`のように記述して親クラスのイニシャライザを呼び出します。
また、プロパティ`numberOfSides`は親クラス`NamedShape`のプロパティを継承しているので、子クラスのプロパティであることを明示するために`self.numberOfSides`と記述しますが、子クラスのイニシャライザであることは自明なため、`self.`キーワードを省略することもできます。

`func area{...}`の部分では、親クラス`NamedShape`にはないメソッド`area`を宣言しています。
一方で、`override func simpleDescription{...}`の部分では、親クラス`NamedShape`のメソッド`simpleDescription`を子クラス`Square`で`オーバーライド(override)`しています。オーバーライドする際は、明示するために`override func ...`のように`override`を先に記述します。

また、メソッド`area{...}`ではプロパティ`sideLength`を2乗することで図形の面積(`Square`は「正方形」)を算出しています。
`let sampleSquare`では、1辺の長さ`sideLength`を`5.2`と設定しているものの、演算結果が`27.040000000000003`(本当の値は`27.04`)となっています。これは、10進数表記の小数を2進数に正確に変換できない`丸め誤差(rounding error)`から誤差が生じています。

10進数の5.2は、整数部と小数部に分けて2進数に`基数変換(radix conversion)`が行われます。整数部の`5`は2進数で`101`と表現することができますが、小数部の`0.2`を小数で表そうとすると、`0.001100110011...`のように`循環小数(recurring decimal)`となるため、計算時に端数調整が必要となります。この端数調整によって誤差が生じます。

### ゲッタ(getter)とセッタ(setter)

`プロパティ`には、**変数の値や属性を取得**する`ゲッタ(getter)`や**変数の値や属性を設定**する`セッタ(setter)`としての役割を持たせることもできます。

プロパティに`ゲッタ`と`セッタ`の役割を持たせたサンプルプログラムは以下の通りです。

```swift:ゲッタとセッタの機能を持つプロパティ
// 親クラスNamedShapeの子クラスEquilateralTriangleのクラス宣言
class EquilateralTriangle: NamedShape {
　　var sideLength: Double = 0.0  // エラー防止のため'0.0'で初期化

　　// イニシャライザ
　　init(sideLength: Double, name: String) {
　　　　self.sideLength = sideLength
　　　　super.init(name: name)
　　　　numberOfSides = 3   // 'self.'キーワードの省略
　　}

　　// ゲッタ・セッタのプロパティperimeter
　　var perimeter: Double {
　　　　// 「1辺の長さ」から「周囲の長さ」を取得
　　　　get {
　　　　　　return 3.0 * sideLength
　　　　}
　　　　// 「周囲の長さ」から「1辺の長さ」を設定
　　　　set {
　　　　　　sideLength = newValue / 3.0
　　　　}
　　}

　　// 1辺の長さを出力するようオーバーライドした関数simpleDescription
　　override func simpleDescription() -> String {
　　　　return "An equilateral triangle with sides of length \(sideLength)."
　　}
}

// 子クラスEquilateralTriangleのインスタンス生成
var sampleTriangle: EquilateralTriangle = EquilateralTriangle(sideLength: 3.1, name: "sample triangle")

print(sampleTriangle.perimeter)
// 実行結果: 9.3

// プロパティperimeterの値を変更
sampleTriangle.perimeter = 9.9

print(sampleTriangle.sideLength)
// 実行結果: 3.3000000000000003
```

クラス`EquilateralTriangle`は、親クラス`NamedShape`を`継承(inherit)`した`子クラス(child class)`です。

`var sideLength: Double = 0.0`の部分では、プロパティ`sideLength`は親クラス`NamedShape`にも存在するプロパティであり、`イニシャライザ`によって値が代入されるため`= 0.0`と初期化する必要はありませんが、**エラー防止**のために`0.0`で初期化しています。

`var perimeter: Double {...}`の部分では、正三角形の「周囲の長さ」を表すクラス`EquilateralTriangle`で新たに追加するプロパティ`perimeter`を宣言しています。
プロパティ`perimeter`は、**「1辺の長さ」を元に「周囲の長さ」を取得**する`ゲッタ`としての役割と、プロパティ`perimeter`に値が代入された場合に、与えられた**「周囲の長さ」を元に「1辺の長さ」を設定**する`セッタ`としての役割を持っています。

`set { sideLength = newValue / 3.0 }`の部分では、プロパティ`perimeter`の値が変更された場合の値を`newValue`とし、`newValue`の値を元に「1辺の長さ」を表すプロパティ`sideLength`が設定されるようにしています。

また、親クラス`NamedShape`は図形が「四角形」であることを前提として作られているため、1辺の長さを出力する際は**`A square`**` with sides of length ...`と出力されるように関数`simpleDescription`を定義していました。
子クラス`EquilateralTriangle`に属する図形は「正三角形」であるため、親クラス`NamedShape`の`simpleDescription()`関数を`override func simpleDescription ...`と記述することで`オーバーライド`しています。

`var sampleTriangle: EquilateralTriangle = ...`の部分では、クラスの`実体(インスタンス)`である`sampleTriangle`を生成し、初期値として「1辺の長さ」を与え、その「1辺の長さ」を元に「周囲の長さ」を取得するゲッタ`perimeter`が機能しているか確認しています。

また、`sampleTriangle.perimeter = 9.9`以降の部分では、インスタンス`sampleTriangle`の「周囲の長さ」を表すプロパティ`perimeter`の値を変更し、変更された「周囲の長さ」の値を元に「1辺の長さ」を設定するセッタ`perimeter`が機能しているか確認しています。
ただし、先述した`丸め誤差`によって、出力される値に**誤差**が生じています。

### プロパティオブザーバ(property observer)

上記のサンプルプログラムにおいて、プロパティ`perimeter`は「(1辺の長さ)⇔(周囲の長さ)」を**演算**によって求め合う`計算型プロパティ(computed property)`でした。

一方で、`計算型プロパティ`と対照的な存在である、値を保持する`格納型プロパティ(stored property)`という種類のプロパティも存在します。
そして、`格納型プロパティ`の値が更新された場合に処理を行う`プロパティオブザーバ(property observer)`という仕組みがあります。`プロパティオブザーバ`は、**プロパティの変更前や変更後の値を処理に使用**したい場合に有効な手法です。

`プロパティオブザーバ`を用いたサンプルプログラムは、以下の通りです。

```swift:プロパティオブザーバ
// クラスTriangleAndSquareのクラス宣言
class TriangleAndSquare {
　　// 
　　var triangle: EquilateralTriangle {
　　　　willSet {
　　　　　　square.sideLength = newValue.sideLength
　　　　}
　　}

　　// 
　　var square: Square {
　　　　willSet {
　　　　　　triangle.sideLength = newValue.sideLength
　　　　}
　　}

　　// イニシャライザ
　　init(size: Double, name: String) {
　　　　// 
　　　　triangle = EquilateralTriangle(sideLength: size, name: name)
　　　　//
　　　　square = Square(sideLength: size, name: name)
　　}
}

// インスタンス生成
var sampleTriangleAndSquare: TriangleAndSquare = TriangleAndSquare(size: 10, name: "sample shape")

print(sampleTriangleAndSquare.square.sideLength)
// 実行結果: 10.0
print(sampleTriangleAndSquare.triangle.sideLength)
// 実行結果: 10.0

// クラスSquare側での値変更
sampleTriangleAndSquare.square = Square(sideLength: 50, name: "larger square")

print(sampleTriangleAndSquare.square.sideLength)
// 実行結果: 50.0
print(sampleTriangleAndSquare.triangle.sideLength)
// 実行結果: 50.0
print(sampleTriangleAndSquare.square.name)
// 実行結果: larger square
print(sampleTriangleAndSquare.triangle.name)
// 実行結果: sample shape
```

クラス`TriangleAndSquare`のインスタンスは、内部に別クラス`EquilateralTriangle`・`Square`のインスタンスを有する`コンポジション(composition; 合成)`の構造を取っています。
クラス`TriangleAndSquare`とクラス`Triangle`・`Square`のようなクラス関係を`has-A関係`と呼びます。

一方で、親クラス`NamedShape`と、クラス`NamedShape`を継承した子クラス`EquilateralTriangle`・`Square`のようなクラス関係を`is-A関係`と呼びます。

`var triangle ...`と`var square ...`の部分では、クラス`TriangleAndSquare`のプロパティ`triangle`・`square`に`プロパティオブザーバ`としての役割を持たせています。

`willSet {...}`の部分では、インスタンスの生成時やプロパティ`triangle`・`square`の参照先の変更時に、もう一方のプロパティ(`triangle`または`square`)に対して、自身の変更されたプロパティが保持するプロパティ`sideLength`を代入させ、互いのプロパティ`sideLength`が同じ値になるように設定しています。
**参照先が変更された「後」の値**を基準としてもう一方のプロパティの値を設定するため、セッタの定義では**`willSet {...}`**を用いています。

`var sampleTriangleAndSquare: TriangleAndSquare ...`の部分では、クラス`TriangleAndSquare`のインスタンス`sampleTriangleAndSquare`を生成しています。
このインスタンスの生成時に、クラス`TriangleAndSquare`のプロパティ`triangle`・`square`が`実体`として生成され、互いに持つプロパティ`sideLength`が同じ値をとるようにセッタが働き合います。

`sampleTriangleAndSquare.square = ...`の部分では、クラス`TriangleAndSquare`のインスタンス`sampleTriangleAndSquare`の参照先をプロパティ`sideLength: 50, name: "larger square"`のクラス`Square`のインスタンス`Square(...)`に変更しています。

参照先の変更によって、クラス`TriangleAndSquare`のプロパティ`square`が持つプロパティ`sideLength`の変更後の値`50(.0)`が変数`newValue`に代入されます。そして、クラス`TriangleAndSquare`のプロパティ`triangle`の`willSet {...}`の部分で、プロパティ`triangle.sideLength`の値が元々格納されていた`10.0`から`50.0`に変更されます。

一方で、セッタとしての機能を持つプロパティ`triangle`・`square`の`willSet {...}`の部分では、それぞれが持つプロパティ`name`の値には言及されていないため、プロパティ`triangle.name`の値は最初に設定された`"sample shape"`のままですが、プロパティ`square.name`の値は`"larger shape"`に変更されていることが分かります。

### オプショナル型インスタンス

`Optional型変数`の宣言時には、型の直後に`?`を付けることで変数が`Optional型`であることを宣言していました。

`Optional型`のクラス型変数(=`インスタンス`)の宣言も同様に、インスタンスの**クラス型の直後**に`?`を付けることで`Optinal型インスタンス`を宣言することができます。

また、`Optional型インスタンス`が持つ`プロパティ`を変数に参照し、`print()`関数で出力する場合は、参照先を記述する際に`Optional型インスタンス`名の直後にオプショナルチェイニング`?`または強制アンラップ`!`を行う必要があります。`print()`関数は、`非Optional型`変数のみでしか引数として認めていないためです。

`Optional型インスタンス`を宣言するサンプルプログラムは以下の通りです。

```swift:オプショナル型インスタンスの生成
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")

// オプショナルチェイニング'?'
let implicitlyUnwrappedOptionalSideLength = optionalSquare?.sideLength
// 強制アンラップ'!'
let forcedUnwrappedOptionalSideLength = optionalSquare!.sideLength

print(implicitlyUnwrappedOptionalSideLength)
// 実行結果: Optional(2.5)
print(forcedUnwrappedOptionalSideLength)
// 実行結果: 2.5
```

## 列挙型と構造体
### 参照型(reference type)と値型(value type)
なお、`クラス`のデータ型は、`参照型(reference type)`であったのに対し、以下で紹介する`列挙型`および`構造体`のデータ型は`値型(value type)`です。
※詳しくは[こちら]
(https://qiita.com/koher/items/bcdbf6578b6edd1f9e0c)

`参照型`と`値型`の挙動の違いを表すサンプルプログラムは、以下の通りです。

```swift:参照型と値型
// 参照型のクラス
class Reference {
　　var a, b: Int

　　// イニシャライザ
　　init(a: Int, b: Int) { self.a = a; self.b = b }
}

// 参照型の構造体
struct Value {
　　var a, b: Int
}

// インスタンスの生成
let reference = Reference(a: 3, b: 5)
let value = Value(a: 3, b: 5)

// 参照型の挙動
reference.a = 6

print("Reference(a: \(reference.a), b: \(reference.b))")
// 実行結果:
// Reference(a: 6, b: 5)

reference = Reference(a: 6, b: 5)
// 実行結果:
// error: cannot assign to value

// 値型の挙動
value.a = 6
// error: cannot assign to property

value = Value(a: 3, b: 5)
// error: cannot assign to value
```

`let ...`の部分では、参照型である`クラス`と、値型である`構造体`のインスタンスを**`定数`として生成**しています。

にもかかわらず、`reference.a = 6`の部分では、`参照型`のインスタンス`reference`のプロパティ`a`を**再設定**することができています。これは、インスタンス`reference`が、初期値である`Reference(a: 3, b: 5)`が確保している**`領域(space)`**しか見ていないためです。

つまり、`参照型`である`クラス`にとって、「`定数`」として`イミュータブル(immutable; 変更不可)`であってほしいのはその「`領域`」であって、**領域に格納されている値ではない**のです。このことは、`reference = Reference(a: 6, b: 5)`の部分で、格納される値は同じではあるものの、領域が異なるデータを参照させようとして`実行時エラー`を吐いていることからも分かります。

一方で、`値型`のインスタンス`value`は、`value.a = 6`および`value = Value(a: 3, b: 5`の部分で「**領域に格納されている値**」および「**`領域`**」を変更しようとして`実行時エラー`が吐き出されました。

このことから、`値型`である`構造体`にとって、「`定数`」として`イミュータブル(immutable; 変更不可)`であってほしいのはその「`領域`」および「**領域に格納されている値**」であることが分かります。

また、先述したように、`構造体`の`ストアドプロパティ(stored property)`はデフォルトで`イミュータブル`ですが、`var`・`mutating`・`inout`のキーワードを用いることで、`ミュータブル(mutable; 変更可能)`な状態に変えることもできます。

さらに、`参照型`と`値型`では、インスタンスをコピーした場合に、元インスタンスからコピーインスタンスに対して「**`渡される(be passed)`もの**」が異なります。
それを確かめる以下のサンプルプログラムに注目しましょう。

```swift:参照型と値型その②
// 「参照型」のクラス
class Reference {
    var a: String
    var b: String
    init(a: String, b: String){
        self.a = a
        self.b = b
    }
    // スワップメソッド
    func swap() {
        var tmp = a
        a = b
        b = tmp
    }
}

// 「値型」の構造体
struct Value {
    var a: String
    var b: String
    init(a: String, b: String){
        self.a = a
        self.b = b
    }
    // スワップメソッド
    mutating func swap2() {
        var tmp = a
        a = b
        b = tmp
    } 
}

// インスタンス生成
var referenceType = Reference(a: "瀧", b: "三葉")
var valueType = Value(a: "瀧", b: "三葉")
// インスタンスのコピー
var referenceTypeCopied = referenceType
var valueTypeCopied = valueType

// 事前チェック
print("事前チェック: \(referenceTypeCopied.a), \(referenceTypeCopied.b)")
// 実行結果: 事前チェック: 瀧, 三葉
print("事前チェック: \(valueTypeCopied.a), \(valueTypeCopied.b)")
// 実行結果: 事前チェック: 瀧, 三葉

// コピーインスタンスのスワップ
referenceTypeCopied.swap()
valueTypeCopied.swap2()

// 検証結果
print("元データ: \(referenceType.a), \(referenceType.b)")
// 実行結果: 元データ: 三葉, 瀧
print("元データ: \(valueType.a), \(valueType.b)")
// 実行結果: 元データ: 瀧, 三葉
print("変更後データ: \(referenceTypeCopied.a), \(referenceTypeCopied.b)")
// 実行結果: 元データ: 三葉, 瀧
print("変更後データ: \(valueTypeCopied.a), \(valueTypeCopied.b)")
// 実行結果: 元データ: 三葉, 瀧
```

`スワップメソッド`の定義では、`参照型`はデフォルトで`ミュータブル`な値を取るため、メソッドの宣言時に、メソッドによって**プロパティの値が変更されることを明示**するための**`mutating`**キーワードは付加されていませんが、`値型`はデフォルトで`イミュータブル`な値を取るため、メソッドの宣言時に`mutating`キーワードを付加しています。

`インスタンス生成`の部分では、クラス・構造体の元インスタンスをそれぞれ`referenceType`・`valueType`として生成しています。
`インスタンスのコピー`の部分では、クラス・構造体のコピーインスタンスをそれぞれ`referenceTypeCopied`・`valueTypeCopied`として生成しています。

`コピーインスタンスのスワップ`の部分では、**`コピーインスタンス`に対して`スワップメソッド`を実行**した結果、`検証結果`の出力結果から分かるように、`参照型`と`値型`で**元データ**に差異が生じています。

`参照型`のインスタンスは、「**参照先**」を渡しています。そのため、**参照先に格納されているデータ(=`ストアドプロパディ`)が変更**されると、元インスタンス・コピーインスタンスの両方で値の変更が生じます。

一方で、`値型`のインスタンスは、「**値**」を渡しています。そのため、コピーインスタンスの`ストアドプロパティ`が変更されても、元インスタンスの`ストアドプロパティ`は変更されません。

### 列挙型(enumeration)

`列挙型(enumeration)`は、**関連するデータを一つにまとめる定数**です。`Swift`における`列挙型`は、`列挙型`の定義にメソッドを含め、動作や機能を実現することもできます。ただし、列挙型によって列挙された`データ`の値を操作することはできません。
値を操作する必要のない、関連性の高い`データ`が複数ある場合は、`var x, y ...`のようにバラバラに書くのではなく、`列挙型`で一まとめにして記述することで、可読性を向上させ、管理しやすくしておきましょう。

ただし、前述したように`列挙型`のデータの値はそもそも**変更することができない**ため、サイズの大きなデータを取り扱う時に、`メモリアドレス`を渡し合う`クラス`はプログラムのサイズがさほど膨らまないのに対し、`データ`をコピーする`列挙型`はプログラムのサイズが顕著に膨らむ、くらいの理解に留めておきましょう。

#### 値型(value type)の列挙型
列挙ケースそれぞれが値を持つような`列挙型`を、「`値型(value type)`の`列挙型`」と呼びます。
`列挙型`を宣言するサンプルプログラムは、以下の通りです。

```swift:値型の列挙型の宣言
enum Rank: Int {
　　case ace = 1
　　case two, three, four, five, six, seven, eight, nine, ten
　　case jack, queen, king

　　func simpleDescription() -> String {
　　　　switch self {
　　　　case .ace: return "ace"
　　　　case .jack: return "jack"
　　　　case .queen: return "queen"
　　　　case .king: return "king"
　　　　default: return String(self.rawValue)
　　　　}
　　}
}

let ace = Rank.ace
let aceRawValue = ace.rawValue

print(ace)
// 実行結果: ace
print(aceRawValue)
// 実行結果: 1
```

`enum Rank: Int {...}`の部分では、`Int型`の列挙型`Rank`を宣言し、関連するデータを一まとめにしています。
ここで、列挙型の列挙された`データ`は`列挙ケース(enumeration case)`と呼ばれます。`列挙ケース`は、`case x`と記述して宣言します。

`case ace = 1`の部分では、列挙ケース`ace`に対して、`Int型`の数値`1`を代入しています。
`列挙ケース`に割り当てられた値(=`整数リテラル(integer literal)`)を、`実体値(raw value)`と呼び、`実体値`の型は`実体型(raw type)`と呼びます。
また、今回のように`実体型`を`Int型`とする列挙型では、列挙ケースそれぞれに実体値を設定しない場合、1番目の列挙ケースの値を基に、2番目以降の列挙ケースにも**自動的に値が連番で代入**されます。つまり、`ace = 1`と代入された時点で、自動的に`two = 2, three = 3, ...`のように値が代入されています。なお、`Int型`の列挙型で1番目の列挙ケースにも値を設定しない場合は、1番目の列挙ケースから順に、`0, 1, 2, ...`と既定の`実体値`が設定されます。

`func simpleDescription ... {...}`の部分では、それぞれの`列挙ケース`に対する処理を記述することで、`列挙ケース`と列挙ケースに依存する`メソッド`を一体のものとして`列挙型`を定義しています。

`let ace = Rank.ace`の部分では、定数`ace`に対して、列挙型`Rank`の列挙ケース`ace`を参照させています。
また、`let aceRawValue = ace.rawValue`の部分では、定数`aceRawValue`に対して、列挙ケース`ace`の持つ実体値`ace.rawValue`を参照させています。

上記プログラムでは、列挙型の`インスタンス`を基に`実体値`を出力しましたが、`実体値`を基に列挙型の`インスタンス`を出力することもできます。

`実体値`を基に`インスタンス`を出力し、出力した`インスタンス`を基に列挙型の持つ`メソッド`を実行するサンプルプログラムは以下の通りです。

```swift:実体値から列挙型のインスタンスを取得
if let convertedRank = Rank(rawValue: 13) {
　　let kingDescription = convertedRank.simpleDescription()
　　print(kingDescription)
}
// 実行結果: king
```

`if let ...`の部分では、イニシャライザ`init?(rawValue:)`を使って、実体値に`13`を持つ列挙型`Rank`のインスタンスを生成し、そのインスタンスを定数`convertedRank`に代入しています。
`オプショナルバインディング`を使用しているのは、例えば`Rank(rawValue: 38)`のように、実体値に`38`を持つ列挙ケースがない場合はインスタンスが`nil`となりますが、`nil`のインスタンスに対してメソッド`simpleDescription`を実行しないようにするためです。

`実体値`から列挙型の`インスタンス`を取得する際は、`if let ...`のように`オプショナルバインディング`を用いるようにしましょう。

#### シンプルな列挙型
なお、**`実体値`を持たない**列挙型も宣言することができます。
`実体値`を持たない列挙型を宣言するサンプルプログラムは、以下の通りです。

```swift:実体値を持たないシンプルな列挙型の宣言
enum Suit {
　　case spades, hearts, diamonds, clubs

　　func simpleDescription() -> String {
　　　　switch self {
　　　　case .spades: return "knight"
　　　　case .hearts: return "priest"
　　　　case .diamonds: return "merchant"
　　　　case .clubs: return "farmer"
　　　　}
　　}
}

let hearts = Suit.hearts
let heartsDescription = hearts.simpleDescription()

print(hearts)
// 実行結果: hearts
print(heartsDescription)
// 実行結果: priest
```

#### 共用型(union type)の列挙型
列挙型`Rank`・`Suit`などの**`値型`の列挙型の列挙ケースは、実体型が一つに限定**されていました。一方で、複数の異なる`タプル(tuple)`の構造を併せ持つことのできる`共用型(union type)`の列挙型も存在します。
`共用型`の列挙型では、それぞれの型が異なる列挙ケースを定義することができます。そして、`switch文`によって、インスタンスの基となる列挙ケースを判定し、判定した列挙ケースによって処理を分岐させることもできます。
以下のサンプルプログラムでは、インスタンスの列挙ケースに基づいて分岐処理を実行しています。

```swift:共用型の列挙型の宣言
enum ServerResponse {
　　case result(String, String)
　　case failure(String)
}

let success = ServerResponse.result("6:00 am", "8:09 pm")
let failure = ServerResponse.failure("Out of cheese.")

switch success {
case let .result(sunrise, sunset):
　　print("Sunrise is at \(sunrise), sunset is at \(sunset).")
case let .failure(message):
　　print("Failure... \(message).")
}
// 実行結果:
// Sunrise is at 6:00 am and sunset is at 8:09 pm.
```

`let ...`の部分では、列挙型`ServerResponse`のインスタンスを生成しています。定数`success`は列挙ケース`result`の、定数`failure`は列挙ケース`failure`のインスタンスです。

そして、`switch success {...}`の部分では、定数`success`が列挙ケース`result`・`failure`のどちらの性質を有するかによって処理を分岐させています。

`case x:`のラベル`x`の部分では、今回のように**ラベル`x`の持つ値が入力によって変化**するため、**`case let`**` y(z ...):`と記述することで、列挙ケース`y`の部分だけを判定材料にするようにします。そして、列挙ケース`y`に合致すれば、仮引数`z`の部分に、ラベル`x`の持つ値(=`実引数(argument)`)が代入されます。

### 構造体(structure)

`構造体`も、列挙型と同様に`値型`のデータであるため、構造体のデータは代入や関数呼び出しの際、値がコピーされ、元のデータの値は変更されません。

```swift:構造体の宣言
struct Card {
　　var rank: Rank
　　var suit: Suit

　　func simpleDescription() -> String {
　　　　return "The \(rank.rawValue) of \(suit)"
　　}
}

let threeOfSpades = Card(rank: .three, suit: .spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

print(threeOfSpades)
// 実行結果:
// Card(rank: main.Rank.three, suit: main.Suit.spades)
print(threeOfSpadesDescription)
// 実行結果:
// The 3 of spades.
```

`let threeOfSpades ...`の部分では、構造体`Card`のインスタンスを生成していますが、出力結果を見ると、プロパティ`rank`・`suit`の中身にそれぞれ`main.`と付いているのが分かります。
これは、プロパティ`Rank.three`・`Suit.spades`がそれぞれ筆者が普段使っている`main.swift`のファイルに属していることを表しています。つまり、ここでの`main`は「**ファイル名**」を指しています。

## プロトコル(protocol)と拡張(extension)

`プロトコル(protocol)`は、**`型`の持つメソッドやプロパティをまとめる抽象的な概念**であり、`C言語`や`Java`でいう`インタフェース`に相当します。
`プロトコル`同様、メソッドやプロパティを一まとめにする`クラス`との違いは、その「**抽象性**」にあります。

`クラス`は**具体性が高い**ため、**インスタンスの生成が可能**です。
一方で、`プロトコル`はあくまで「**概念**」であるため、`プロトコル`の宣言時には、メソッドやプロパティの中身までは記述せず、メソッドやプロパティの持つ**性質**だけを記述します。
例えば、`メソッド`の宣言では、ストアドプロパティの値が変更される場合、その旨を明示する`mutating`キーワードだけを付加し、`{...}`にあたるコードブロックは記述しません。
また、`プロパティ`の宣言では、プロパティの性質である`定数・変数`および`型`以外に、「**`アクセス制御(accessibility)`**」を「`読み出し(read)`」の`get`、「`書き出し(write)`」の`set`で記述するだけであり、プロパティの持つ`値`までは記述しません。

### プロトコルの宣言

プロトコルを宣言するサンプルプログラムは、以下の通りです。

```swift:プロトコルの宣言
protocol SampleProtocol {
　　var simpleDescription: String { get }

　　mutating func adjust()
}
```

### プロトコルの採用(adopt)

宣言した`プロトコル`のプロパティ・メソッドを`オブジェクト`に定義することをプロトコルを「`採用(adopt)する`」といいます。また、プロトコルを採用されたオブジェクトは、そのプロトコルに「**`適合(confirm; 準拠)`**している」といいます。

`プロトコル`を`オブジェクト`に採用するサンプルプログラムは、以下の通りです。

```swift:プロトコルの採用
class SimpleClass: SampleProtocol {
　　var simpleDescription: String = "A very simple class."
　　var anotherProperty: Int = 69105

　　func adjust() {
　　　　simpleDescription += " Now 100% adjusted."
　　}
}

// インスタンスの生成
var a = SimpleClass()

print(a.simpleDescription)
// 実行結果:
// A very simple class.

// プロパティa.simpleDescriptionに" Now 100% adjusted."を追加
a.adjust()

print(a.simpleDescription)
// 実行結果:
// A very simple class. Now 100% adjusted.

struct SimpleStructure: SampleProtocol {
　　var simpleDescription: String = "A simple structure."
　　mutating func adjust() {
　　　　simpleDescription += "(adjusted)"
　　}
}

// インスタンスの生成
var b = SimpleStructure()

print(b.simpleDescription)
// 実行結果:
// A simple structure.

// プロパティb.simpleDescriptionに"(adjusted)"を追加
b.adjust()

print(b.simpleDescription)
// 実行結果:
// A simple structure.(adjusted)
```

プロトコルの`採用`は、クラスや構造体の宣言時に、`型アノテーション`として採用する`プロトコル`を記述するだけです。

`プロトコル`の宣言では、プロトコルが持つ**プロパティ・メソッドの中身を定義しない**ため、プロトコルを採用する各オブジェクト宣言の中で、プロパティ・メソッドを**`実装(implement)`**します。
オブジェクトの宣言では、プロトコルにないプロパティ・メソッドを独自に追加することも可能です。ただし、各オブジェクトは、**プロトコルで定めたプロパティ・メソッドを必ず含んで**いなければなりません。

ここで、プロトコルSampleProtocolのメソッド`adjust()`の`実装`部分に注目しましょう。

`参照型`であるクラス`SimpleClass`では、実装する際に`func adjust() {...}`と今まで通りの定義を行っています。

一方で、`値型`である構造体`SimpleStructure`では、実装時に`mutating func adjust() {...}`と、`mutating`キーワードを付加しています。
`mutating`キーワードは、プロパティの「**`値`**」**を変更**するメソッドに対して記述します。なお、ここでの「変更」は、「`暗黙的(implecit)`な`再代入(reassign)`」を指しています。そのため、定数に格納されている`値型`のインスタンス(=`ストアドプロパティ`)には実行できません。

クラスは「`参照型`」であるため、`adjust()`メソッドによって変更されるのは、`値`ではなく`参照先`です。
今回の場合は、プロパティ`simpleDescription`は初期値として`"A very simple class"`を参照していましたが、`adjust()`メソッドによって、**参照先を**`"A very simple class. Now 100% adjusted."`**に変更**しています。初期値として指定されたメモリアドレスには`"A very simple class"`という**値が残り続け**、新たに`"A very simple class. Now 100% adjusted."`の値を格納するメモリアドレスを参照しているのです。
以上の理由から、`mutating`キーワードは記述しません。

### プロトコルの拡張(extension)

プロトコルは、`クラス`や`構造体`といった`オブジェクト`に限らず、`データ型`に対しても採用することができます。ただし、`データ型`は既定で定義されているため、「定義を拡げる」という意味で「`拡張(extension)`」と呼ばれます。

`データ型`を`拡張`するサンプルプログラムは、以下の通りです。

```swift:データ型の拡張
extension Int: SampleProtocol {
　　var simpleDescription: String {
　　　　return "The number \(self)"
　　}

　　mutating func adjust() {
　　　　self += 42
　　}
}

var num: Int = 7

print(num)
// 実行結果: 7
print(num.simpleDescription)
// 実行結果: The number 7

num.adjust()

print(num)
// 実行結果: 49
print(num.simpleDescription)
// 実行結果: The number 49
```

### 変数(variable)・定数(constant)へのプロトコルの採用

`プロトコル`は、様々な`オブジェクト`に採用することができます。
`変数・定数`もオブジェクトの一つであるため、プロトコルを採用することができます。

以下のサンプルプログラムに注目しましょう。

```swift:定数へのプロトコルの採用
let protocolValue: SampleProtocol = a  // aはクラスSimpleClassのインスタンス

print(protocolValue.simpleDescription)
// 実行結果:
// A very simple class. Now 100% adjusted.
print(protocolValue.anotherProperty)
// 実行結果:
// error: value of type 'SampleProtocol' has no member 'anotherProperty'
```

定数`protocolValue`のデータ型は`SampleProtocol`であるため、クラス`SimpleClass`の値を持つインスタンス`a`が代入されていても、**プロトコル`SampleProtocol`が持つプロパティ**しか格納されていません。
そのため、定数`protocolValue`は、クラス`SimpleClass`で独自に作られたプロパティ`anotherProperty`を有していません。

## エラー処理(error handling)

システムを作成するにあたって、発生する可能性のある`エラー(error)`に対して、その**発生**と**内容**を通知するような処理を定義しておくのが望ましいです。

`Swift`では、プログラムの実行中に何らかの原因によって通常処理が継続できなくなった場合、適切な呼び出し位置に一気に戻り、状況に応じた処理を行う`エラー処理構文(error handling syntax)`という仕組みが存在します。

### エラーの定義

まずは、エラーを定義するサンプルプログラムに注目しましょう。

```swift:エラーの定義
enum PrinterError: Error {
　　case outOfPaper
　　case noToner
　　case onFire
}
```

エラーの種類は多種多様ですが、あらかじめ想定されるエラーを区分し、その種類ごとに`列挙型`でまとめておくと、**可読性が向上**します。

### エラー通報関数(throwing function)の定義

また、エラーを`投げる(throw)`可能性のある関数を、`エラー通報関数(throwing function)`と呼びます。

`エラー通報関数`を定義するサンプルプログラムは、以下の通りです。

```swift:エラー通報関数の定義
func send(job: Int, toPrinter printerName: String) throws -> String {
　　switch printerName {
　　case "Never Has Paper": throw PrinterError.outOfPaper
　　case "Never Has Toner": throw PrinterError.noToner
　　case "Power Strip": throw PrinterError.onFire
　　default: break
　　}
　　return "Job sent."
}
```

引数リストの`toPrinter printerName: String`の部分では、`toPrinter`を`仮引数ラベル(parameter label)`として、仮引数`printerName`を設定しています。`実引数(argument)`を定義する際は、**仮引数ラベル**である`toPrinter:`を使用します。

`エラー通報関数`の定義では、引数リスト`(...)`の直後に`throws`キーワードを付ける必要があります。また、実際にエラーを投げる部分では`throw`を記述し、その直後に投げるエラーの種類を記述します。

`func send(...) throws -> String`の部分では、関数`send(...)`がエラーを投げる可能性があることを示唆しています。

`if ... { throw PrinterError.noToner}`の部分では、条件に一致する場合はエラー`PrinterError.noToner`を投げるように定義しています。

### エラーの捕捉(catch)

関数によってエラーが投げられた場合、そのエラーを`捕捉(catch)`してエラーに対処する必要があります。
また、エラーを投げる関数を実行する際は、`try`キーワードを付けて呼び出す必要があります。

エラーの`捕捉`は、`do-catch構文(do-catch syntax)`の`do節(do clause)`内部で関数の呼び出しを行うことで、エラーに対応する`catch節(catch clause)`でエラーを`捕捉`することができます。

エラーが投げられると、投げられた`エラーの値`と`catch節`の条件で`パターンマッチング`を行います。`catch節`は複数個連続して定義することができますが、**`パターンマッチング`は上から順に実行**されます。そのため、具体的な条件を指定する`catch節`を上に置き、包括的な条件を指定する`catch節`は下に置くようにしましょう。

なお、エラーが発生した場合、そのエラーが`捕捉`されるまで処理の呼び出し元に戻り続けますが、この動作をエラーの`伝播(propagation)`と呼びます。

エラーの`捕捉`を行うサンプルプログラムは、以下の通りです。

```swift:エラー通報関数の実行とエラーの捕捉
do {
　　let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")
　　print(printerResponse)
} catch {
　　print(error)
}
// 実行結果: Job sent.

do {
　　let printerResponse = try send(job: 1050, toPrinter: "Never Has Toner")
　　print(printerResponse)
} catch {
　　print(error)
}
// 実行結果: noToner
```

上記プログラムでは、`エラーパターン`に関わらず全てのエラーを`捕捉`する`catch節`でエラーを捕捉しています。全てのエラーを捕捉する`catch節`では、**`error`**という名前の定数で**エラーの値を参照**することができます。

```swift:複数のパターンマッチング
do {
　　let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")
　　print(printerResponse)
} catch PrinterError.onFire {
　　print("I'll just put this over here, with the rest of fire.")
} catch let printerError as PrinterError {
　　print("PrinterError: \(printerError).")
} catch {
　　print(error)
}
// 実行結果: Job sent.

do {
　　let printerResponse = try send(job: 1440, toPrinter: "Power Strip")
　　print(printerResponse)
} catch PrinterError.onFire {
　　print("I'll just put this over here, with the rest of fire.")
} catch let printerError as PrinterError {
　　print("PrinterError: \(printerError).")
} catch {
　　print(error)
}
// 実行結果:
// I'll just put this over here, with the rest of fire.

do {
　　let printerResponse = try send(job: 1440, toPrinter: "Never Has Paper")
　　print(printerResponse)
} catch PrinterError.onFire {
　　print("I'll just put this over here, with the rest of fire.")
} catch let printerError as PrinterError {
　　print("PrinterError: \(printerError).")
} catch {
　　print(error)
}
// 実行結果:
// PrinterError: outOfPaper.
```

`catch PrinterError.onFire {...}`の部分では、`捕捉`するエラーパターンを、エラー`PrinterError.onFire`と指定しています。

`catch let printerError as PrinterError`の部分では、`捕捉`するエラーパターンを、エラー`PrinterError`と指定し、条件に該当する場合は、そのエラーを定数`printerError`に代入しています。
また、`キャスト演算子(cast operator)`である`as`によって、定数`printerError`のデータ型を`PrinterError`に`キャスト`(=`型変換`)しています。

最後の`catch`の部分では、上記2パターンに該当しないエラーパターンを捕捉しています。なお、**`catch`は`catch let error`と同義**です。

### オプショナル型への変換(convert)によるエラー処理

`エラー通報関数`の呼び出し方として、**`try?`を使って呼び出す**方法も存在します。

`try?`を使うことで、返却される値が`オプショナル型`に変換されます。つまり、**エラーが発生する場合**は**`nil`**、**発生しない場合**は**`オプショナル型`で値が返却**されます。

この方法は容易に扱うことができますが、**エラーの原因(=エラーパターン)は特定できません**。

```swift:実行結果をオプショナル型に変換
let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")
let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner")

print(printerSuccess)
// 実行結果: Optional("Job sent.")
print(printerFailure)
// 実行結果: nil
```

エラーが発生する場合に`nil`が返却される理由は、関数`send`のコードブロックにあります。

関数`send`のコードブロックに注目すると、エラーが発生しない場合は`return "Job sent."`と、返却値が存在します。一方で、エラーが発生する場合は`throw <エラー>`のように、エラーが投げられるだけで返却値はありません。
よって、**返却値がない**ため、実行結果が`nil`になります。

### 処理の中断・終了時の処理(defer文)

エラーの発生に伴い、コードブロック内の処理が中断される場合があります。一方で、エラーが発生せず、コードブロック内の処理が正常に終了する場合もあります。

どちらの場合でも**最後に必ず実行してほしい処理**がある場合は、`defer文(defer statement)`を使いましょう。

defer文を使用したサンプルプログラムは、以下の通りです。

```swift:defer文の使用
var fridgeIsOpen: Bool = false
let fridgeContent: [String] = ["milk", "eggs", "leftovers"]

func fridgeContains(_ food: String) -> Bool {
　　fridgeIsOpen = true
　　defer {
　　　　fridgeIsOpen = false
　　}
　　let result: Bool = fridgeContent.contains(food)
　　return result
}

print(fridgeContains("banana"))
// 実行結果: false
print(fridgeContains("milk"))
// 実行結果: true
print(fridgeContent)
// 実行結果: ["milk", "eggs", "leftovers"]
print(fridgeIsOpen)
// 実行結果: false
```

変数`fridgeIsOpen`は、冷蔵庫の開閉状態を示すフラグです。

関数`fridgeContains`は、指定した食べ物が冷蔵庫内に入っているか確認するメソッドで、確認のために最初に冷蔵庫を開けます(=`fridgeIsOpen = true`)。
`let result ...`部分の`.contains(x)`メソッドは、**対象のプロパティに引数`x`が含まれているかどうかを`Bool型`で返す**メソッドです。

`defer {...}`の部分では、`defer文`が記述される、**1つ外側のコードブロック内の処理が中断または終了した時**に、**必ず`defer文`のコードブロック`{...}`を実行**するよう宣言しています。
今回の場合は、確認のために開けた冷蔵庫を閉める(`fridgeIsOpen = false`)ように宣言しています。

## ジェネリクス(generics)

`ジェネリクス(generics)`とは、型をパラメータとしてプログラムを記述するための機能です。

これまでのオブジェクトは、**特定の型を指定**して宣言していました。
`ジェネリクス`は、山括弧`<>`を用いることで、任意の型を`型パラメータ(プレースホルダ)`として指定することができます。この`型パラメータ`によって、プログラムの中でオブジェクトに対して、具体的な型をパラメータとして与えながら、**新しい型を作成**することができます。

### ジェネリクス関数(generics function)

`ジェネリクス`の機能を用いて宣言する関数を、`ジェネリクス関数(generics function; 総称関数, 汎用関数)`と呼びます。

`ジェネリクス関数`を宣言するサンプルプログラムは、以下の通りです。

```swift:ジェネリクス関数の宣言
func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
　　var result = [Item]()
　　for _ in 0..<numberOfTimes {
　　　　result.append(item)
　　}
　　print(type(of: result))
　　// 実行結果: Array<String>
　　return result
}

print(makeArray(repeating: "knock", numberOfTimes: 4))
// 実行結果:
// ["knock", "knock", "knock", "knock"]
```

`func makeArray<Item>(...)`の部分では、`型パラメータ`として`Item`を与えながら、新たな型`Item`を作成しています。作成した時点では、型`Item`が宣言されただけであり、実体である`インスタンス`は生成されていません。

`var result = [Item]()`の部分では、新たに作成した`Item型`の配列`[Item]`のインスタンスを、既定イニシャライザ`()`を用いて生成し、変数`result`に代入しています。

`for _ in 0..<numberOfTimes {...}`の部分では、定数を`ワイルドカード(wildcard)`である`_`として、`範囲演算子(range operator)`である`..<`を用いて、`0`回目から`numberOfTimes - 1`回目まで`numberOfTimes`回の繰り返し処理を行っています。

`result.append(item)`の部分では、`Array`型のメソッド`.append(x)`を用いて、仮引数`x`を配列の要素に追加しています。

ここで、変数`result`には型パラメータが`Item`の配列`[Item]`を代入しましたが、`型推論`によって変数`result`の型が`Array<String>`(=`[String]`)になっていることが分かります。
`型パラメータ`はあくまで`プレースホルダ`として**領域を確保しているだけ**であり、**型推論によって適切な型に変換される**のです。

### ジェネリクスによる型定義

`ジェネリクス`機能を用いた関数である`ジェネリクス関数`の次は、`ジェネリクス`機能を用いた`型`の定義に注目しましょう。

標準ライブラリで定義されている`Optional型`の型の再定義を行うサンプルプログラムは、以下の通りです。

```swift:オプショナル型の再定義
enum OptionalValue<Wrapped> {
　　case none
　　case some(Wrapped)
}

var possibleInteger: OptionalValue<Int> = .none
print(possibleInteger)
// 実行結果: none
print(type(of: possibleInteger))
// 実行結果: OptionalValue<Int>

possibleInteger = .some(100)

print(possibleInteger)
// 実行結果: some(100)
print(type(of: possibleInteger))
// 実行結果: OptionalValue<Int>
```

`Optional型`は、値が存在しなければ`nil`を、値`x`が存在すれば`Optional(x)`を出力する型でした。

`enum OptionalValue<Wrapped>`の部分では、`共用型`の列挙型の名前を`OptionalValue`、型パラメータとして`Wrapped`を設定しながら、値が存在しない場合の列挙ケースを`none`、値が存在する場合の列挙ケースを`some(Wrapped)`と定義しています。

`var possibleInteger ...`の部分では、型パラメータを`<Wrapped>`とする列挙型`OptionalValue<Wrapped>`のインスタンス変数`possibleInteger`に対して、データ型を`OptionalValue<Int>`、列挙ケースを`.none`に指定して代入しています。

`<Wrapped>`は、領域を確保するだけで機能を持たない型パラメータのため、実際のデータ型として`(OptionalValue)<Int>`を指定しています。

`Int(OptionalValue<Int>)`型であるにも関わらず、列挙ケース名と同値である`none`を値として格納できているのは、変数`possibleInteger`が列挙型`OptionalValue<Wrapped>`を`採用`しており、その列挙ケース`none`には`Wrapped`の記述がなく、`Wrapped`から独立しているためです。

### 型パラメータ(type parameter)の記述

型パラメータの書き方は以下の通りです。

- `<T>`: `T`を型パラメータとして定義
- `<T,U>`: `T`および`U`を型パラメータとして定義
- `<T: OtherType>`: `T`は、プロトコル`OtherType`に`適合`またはクラス`OtherType`またはクラス`OtherType`のサブクラス
- `T: OtherType`: 同上
- `where 条件`: 型パラメータの条件指定
- `T == U`: 「型(パラメータ)T == 型(パラメータ)U」が条件

様々な条件を指定した型パラメータを定義するサンプルプログラムは、以下の通りです。

```swift:型パラメータの条件指定
func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool where T.Element: Equatable, T.Element == U.Element {
　　for lhsItem in lhs {
　　　　for rhsItem in rhs {
　　　　　　if lhsItem == rhsItem {
　　　　　　　　return true
　　　　　　}
　　　　}
　　}
　　return false
}

print(anyCommonElements([1, 2, 3], [3]))
// 実行結果: true
```

`func anyCommonElements<T: Sequence, U: Sequence> ...`の部分では、**型パラメータ`T, U`は、それぞれプロトコル`Sequence`に準拠**していなければならないという1つ目の条件を指定しています。

`where T.Element: Equatable, T.Element == U.Element`の部分では、2つ目の条件として、「型パラメータ`T`の要素はプロトコル`Equatable`に準拠している」**かつ**「型パラメータ`T`の要素のデータ型は、型パラメータ`U`の要素のデータ型と一致している」という**`論理積(logical conjunction)`**の条件を指定しています。

プロトコル`Equatable`は、**`オブジェクト`を比較**するプロトコルであり、標準ライブラリで`Int型`や`String型`など多くのデータ型が`適合`するよう定義されています。

補足ですが、関数`anyCommonElements`は2つの`Sequence型`の値を比較し、共通する要素があれば`true`を、共通する要素がなければ`false`を返しています。



<br>
以上で`A Swift Tour`の説明は終わりです。

かなり長くなりましたが、`A Swift Tour`で紹介されているサンプルプログラムを補足しながら説明していきました。

独学のため、誤りもあると思いますが、コメントにて教えていただけると幸いです。

ここまでお読みいただき、ありがとうございました。