Menu
CoddyTech

Melindungi State

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Swift di Coddy. Pelajaran 19 dari 57.

Invarian adalah aturan yang harus selalu berlaku untuk suatu nilai, seperti "saldo tidak pernah negatif". Tipe melindungi invariannya dengan memeriksa setiap perubahan sebelum menerapkannya:

struct BankAccount {
    private(set) var balance = 0

    mutating func withdraw(_ amount: Int) -> Bool {
        guard amount > 0, amount <= balance else { return false }
        balance -= amount
        return true
    }

    mutating func deposit(_ amount: Int) {
        guard amount > 0 else { return }
        balance += amount
    }
}

var acc = BankAccount()
acc.deposit(100)
print(acc.withdraw(150))
print(acc.withdraw(40))
print(acc.balance)

Output:

false
true
60

Ketika pemanggil perlu mengetahui alasan perubahan ditolak, method dapat melempar error alih-alih mengembalikan false. Tipe error adalah enum yang sesuai dengan Error:

enum TransferError: Error {
    case invalidAmount
    case insufficientFunds(missing: Int)
}

struct Account {
    private(set) var balance: Int

    mutating func withdraw(_ amount: Int) throws {
        guard amount > 0 else { throw TransferError.invalidAmount }
        guard amount <= balance else { throw TransferError.insufficientFunds(missing: amount - balance) }
        balance -= amount
    }
}

var acc = Account(balance: 30)
do {
    try acc.withdraw(50)
} catch TransferError.insufficientFunds(let missing) {
    print("missing \(missing)")
} catch {
    print("other error")
}

Output:

missing 20

Letakkan setiap perubahan pada data yang dilindungi di dalam method yang memeriksanya. Jika property dapat diatur dari luar, baris kode mana pun dapat melanggar aturan tanpa diketahui oleh tipe tersebut:

struct Temperature {
    private(set) var kelvin: Double   // harus tetap >= 0
    mutating func cool(by amount: Double) {
        kelvin = max(0, kelvin - amount)   // satu-satunya cara untuk menurunkan nilainya
    }
}

Operasi yang mengubah beberapa properti harus menjaga semuanya tetap konsisten, bahkan jika operasi gagal di tengah jalan. Periksa semuanya terlebih dahulu, lalu ubah statusnya:

struct Inventory {
    private(set) var stock: [String: Int] = ["tea": 2, "jam": 1]

    mutating func sell(_ items: [String]) -> Bool {
        var needed: [String: Int] = [:]
        for i in items { needed[i, default: 0] += 1 }
        for (item, n) in needed where (stock[item] ?? 0) < n { return false }
        for (item, n) in needed { stock[item]! -= n }
        return true
    }
}

var inv = Inventory()
print(inv.sell(["tea", "jam", "jam"]))
print(inv.stock["tea"]!)
print(inv.sell(["tea", "jam"]))
print(inv.stock["tea"]!)

Output:

false
2
true
1
challenge icon

Tantangan

Mudah

Lengkapi struct Seats, yang menjual tiket untuk sebuah pertunjukan dengan capacity kursi. sold bersifat private(set). buy(_:) melempar TicketError.invalidCount jika jumlahnya kurang dari 1, TicketError.soldOut jika tidak ada kursi tersisa, dan TicketError.notEnough(left:) jika jumlah kursi tersisa lebih sedikit daripada yang diminta. Jika tidak, fungsi ini menambahkan tiket ke sold.

Kode yang disediakan membaca kapasitas dan satu jumlah yang diminta pada setiap baris. Untuk setiap jumlah, kode mencetak sold 3, left 7, invalid count, sold out atau only 2 left.

Tulis kodemu di TicketError.swift dan Seats.swift. main.swift berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

// Kode input/output yang disediakan: biarkan apa adanya
var input: [String] = []
while let line = readLine() { input.append(line) }
var seats = Seats(capacity: Int(input[0])!)
for line in input.dropFirst() {
    let n = Int(line)!
    do {
        try seats.buy(n)
        print("sold \(n), left \(seats.capacity - seats.sold)")
    } catch TicketError.invalidCount {
        print("invalid count")
    } catch TicketError.soldOut {
        print("sold out")
    } catch TicketError.notEnough(let left) {
        print("only \(left) left")
    } catch {
        print("unexpected")
    }
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Playground Swift