Swift入門 #2

記念すべき第2回です
やはり、いつもと違う言語の仕様を学ぶと、「その機能欲しい」「その機能をこっちの言語で実装できないか」など考えられるので良いと思い、続けます☺️

参考資料：[改訂新版Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plus) | 石川 洋資, 西山 勇世 |本 | 通販 | Amazon](https://www.amazon.co.jp/%E6%94%B9%E8%A8%82%E6%96%B0%E7%89%88-Swift%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-%E7%9B%B4%E6%84%9F%E7%9A%84%E3%81%AA%E6%96%87%E6%B3%95%E3%81%A8%E5%AE%89%E5%85%A8%E6%80%A7%E3%82%92%E5%85%BC%E3%81%AD%E5%82%99%E3%81%88%E3%81%9F%E8%A8%80%E8%AA%9E-PRESS-plus/dp/477419414X/ref=pd_lpo_sbs_14_img_0?_encoding=UTF8&psc=1&refRID=8AKW81D2VX88MFHTDGKM)

## 条件分岐
条件により分岐をしていく方法ですね
### if文

```swift
let bool: Bool = true
if bool {
} else {
}
```

```swift
let i: Int = 1
if i <= 0 {
} else if i < 3 {
	// ここに入る
} else {
}
```

上のiの判定をしたい場合、caseを使って簡単に書くこともできます

```swift
if case 1..<3 = i {
	// 1 <= i < 3
}
```

### switch文

```swift
enum Hair {
	case short
	case medium
	case long
}

let hair = Hair.short
switch hair {
case .short, .medium:
	print(hair)
case .long:
	print(hair)
}
```
swiftのswitch文はbreakを書かなくてもbreakを実行してくれます。でも、caseの内容がなにもないときはbreakを明示的に書かなければなりません。
複数のcaseを定義したい場合は、,で区切ります。

```swift
let i: Int = 1
switch i {
case 0..<2:
	print(i)
case 3..<Int.max:
	print(i)
default:
	print(i)
}
```
このように範囲を指定して分岐させることもできます。先ほどは、すべての条件を網羅していたのでdefaultが必要なかったのですが、今回は負の値の場合の条件が足りないためdefaultが必要です。
この網羅性のチェックもコンパイルエラーとして表示してくれます。

```swift
let i: Int = 4
switch i {
case 0..<10 where i % 2 == 0:
	print(i)
default:
	break
}
```
caseは0<=i<10の範囲のパターンかどうかで分岐します。そこにwhereで条件式を追加することができます。
今回は、0<=i<10の範囲内かつ偶数の場合、print()が実行されます。

## 列挙型
先ほど出てきた列挙型enumです。

```swift
enum Hair {
	case short
	case medium
	case long
}
```
### hashValue

```swift
let hair = Hair.long.hashValue // 2
```
標準で使えるプロパティです。1つ目のcaseから０で始まり順番になります。
### rawValue
それぞれのcaseに対応した値を定義できます。

```swift
enum Hair: String {
	case short = "短い"
	case medium = "中くらい"
	case long = "長い"
}

let hair = Hair.long.rawValue // 長い
```
Int・String・Double・Characterなどの型が使用できます。

```swift
enum Hair: String {
	case short
	case medium
	case long
}

let hair = Hair.long.rawValue // long
```
IntとStringにはdefaultのrawValueが定義されています。
Int: hashValueと一緒で0から順番
String: caseの名前をそのまま文字列にする
### メソッド

```swift
enum Hair: String {
	case short
	case medium
	case long
	
	init?(rawValue: String) {
		switch rawValue {
		case "short":
			self = .short
		case "medium":
			self = .medium
		case "long":
			self = .long
		default:
			return nil
		}
	}

	func getlength() -> Int {
		switch self {
		case .short:
			return 10
		case .medium:
			return 20
		case .long:
			return 30
		}
	}
}

let hair = Hair(rawValue: "short") // short
let length = hair?.getlength() // 10
```
初期化も書くことができます。init?は初期化に失敗した時にnilを返します。
またメソッドを追加することもできます。switchに自分自身のselfを渡して分岐させることもできます。
### プロパティ

```swift
enum Hair: String {
	case short
	case medium
	case long
	
// ストアドプロパティ
//	let name = ""

// コンピューテッドプロパティ
	var name: String {
		switch self {
		case .short:
			return ""
		case .medium:
			return ""
		case .long:
			return ""
		}
	}
}
```
ストアドプロパティは持つことができません。ストアドプロパティは、値を保持するプロパティです。
コンピューテッドプロパティは持つことができます。コンピューテッドプロパティは値を保持せず算出するプロパティです。
### 連想値
enumのcaseそれぞれに値を持たせることができます。

```swift
enum Result<T> {
	case Success(T)
	case Error(Error)
}
```
RxSwiftでも使われているResult型です。非同期の結果をハンドリングする時とかに役立ちます。

```swift
enum MyError: Error {
	case LTE
	case WIFI
}

func some(bool: Bool) -> Result<Int> {
	if bool {
		return .Success(10)
	} else {
		return .Error(MyError.LTE)
	}
}
```
Errorもenumで定義できます。

```swift
let result = some(bool: true)
switch result {
case .Success(let value):
	print(value) // 10
case .Error(let error):
	print(error) // LTE
}
```
結果はこのようにハンドリングできます。今回はError呼ばれませんが、呼ばれた場合は、LTEがerror変数に入ります。

ジェネリクス・列挙型・列挙型.連想値・switchの組み合わせでこのようなことができます。組み合わせでできることを考えていくのもswiftの面白いところです。