---
# System prepended metadata

title: 'Day 11 - Access control, static properties and methods, and checkpoint 6'

---

# Day 11 - Access control, static properties and methods, and checkpoint 6

## How to limit access to internal data using access control

- 有些property的值不想被struct外部讀寫，可以在前面加上 `private`
    ```
    struct BankAccount {
      private var funds = 0

      mutating func deposit(amount: Int) {
        funds += amount
      }

      mutating func withdraw(amount: Int) -> Bool {
        if funds >= amount {
          funds -= amount
          return true
        } else {
          return false
        }
      }
    }
    ```
- access control：管理property或method是否可以從外部存取
- 存取權種類
    | 關鍵字          | 說明                      |
    | --------       | --------                 |
    | private        | 不讓任何struct以外的地方使用 |
    | fileprivate    | 不讓目前檔案以外的地方使用    |
    | public         | 任何地方都可以使用          |
    | private(set)   | 外部只能讀不能寫            |
- 如果有特別指定存取權，通常也需要自訂initializer

### Optional: What’s the point of access control?

- 有時候權限控制是用在不屬於你的code裡面，例如Apple的API，所以你必須遵守這些存取權
- 就算是自己可以更動的code，access control也讓我們知道一個值應該怎麼被使用，所以不會是無意義的

## Static properties and methods

- 將property或method標為 `static` 表示這些操作是針對 struct 本身，而非 instance，因此針對property操作的 method 不需要加上 `mutating` 也能正確執行
    ```
    struct School {
      static var studentCount = 0

      static func add(student: String) {
        print("\(student) joined the school.")
        studentCount += 1
      }
    }

    School.add(student: "Taylor")
    ```
- 不能在 static 的property或method裡針對 non-static操作；反之則可以
- 兩種 self 的含義
    - `self`：struct 目前的 value
    - `Self`：struct 目前的 type
- `static` 的 use case
    - 常用data
        ```
        struct AppData {
          static let version = "1.3 beta 2"
          static let saveFilename = "settings.json"
          static let homeURL = "https://www.hackingwithswift.com"
        }
        ```
    - 範例data
        ```
        struct Employee {
          let username: String
          let password: String

          static let example = Employee(username: "cfeghi", password: "h4irfo0rce0ne")
        }
        ```

## Summary: Structs

- 我們可以用 `struct` 關鍵字創建自己的 struct
- struct 可以有它們自己的 properties 和 methods
- 如果一個 method 會更動到 struct 的 property，他必須要是 `mutating` 的
- struct 可以有 `stored` 和 `computed` properties
- 我們可以附加 `didSet` 和 `willSet` （property observers）在property上
- Swift用所有struct的property名稱為它們產生initializer
- 如果想要的話也可以用自訂的initializer覆蓋預設的
    - 必須確保所有property都有initial value
- access control限制什麼code能使用properties 和 methods
- static properties 和 methods 是直接被附加在struct上的

## Checkpoint 6

### 題目
- 創建一個struct儲存一台車的資訊，包括：
    - 車型
    - 座位數量
    - 排檔
- 增加一個可以升檔／降檔的method
- 考慮變數和權限控制
- 不允許無效的檔位，限制在1到10檔

### 答案

```   
struct Car {
  static let model = "Toyota Yaris"
  static let numberOfSeats = 5
  var currentGear: Int

  mutating func changeGears(gear: Int) {
    if gear < 1 {
      currentGear = 1
    } else if gear > 10 {
      currentGear = 10
    } else {
      currentGear = gear
    }
  }
}

var car = Car(currentGear: 10)
print(car.currentGear)  // 10
car.changeGears(gear: 5)
print(car.currentGear)  // 5
car.changeGears(gear: 0)
print(car.currentGear)  // 1
car.changeGears(gear: 11)
print(car.currentGear)  // 10
```