Menu
Coddy logo textTech

Durumu Koruma

Coddy'nin Swift Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 19 / 57.

Değişmez, "bir bakiye hiçbir zaman negatif değildir" gibi, bir değer için her zaman geçerli olması gereken bir kuraldır. Bir tür, uygulamadan önce her değişikliği kontrol ederek değişmezlerini korur:

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)

Çıktı:

false
true
60

Bir çağıranın bir değişikliğin neden reddedildiğini bilmesi gerektiğinde, metot false döndürmek yerine bir hata fırlatabilir. Hata türü, Error protokolüne uyan bir enum'dur:

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")
}

Çıktı:

missing 20

Korumalı verilerdeki her değişikliği, bu veriyi denetleyen yöntemlerin içinde tutun. Özellik dışarıdan ayarlanabilir olsaydı, herhangi bir kod satırı tür bunu fark etmeden kuralı ihlal edebilirdi:

struct Temperature {
    private(set) var kelvin: Double   // &gt;= 0 kalmalı
    mutating func cool(by amount: Double) {
        kelvin = max(0, kelvin - amount)   // onu düşürmenin tek yolu
    }
}

Birden fazla özelliği değiştiren bir işlem, işlem yarıda başarısız olsa bile bunları tutarlı bırakmalıdır. Önce her şeyi kontrol edin, ardından durumu değiştirin:

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"]!)

Çıktı:

false
2
true
1
challenge icon

Görev

Kolay

Seats struct'ını tamamla; bu struct, capacity sayıda koltuğu olan bir gösteri için bilet satar. sold, private(set) olarak tanımlıdır. buy(_:), 1'in altındaki bir sayı için TicketError.invalidCount, boş koltuk kalmadığında TicketError.soldOut ve istenenden daha az koltuk kaldığında TicketError.notEnough(left:) hatalarını verir; aksi takdirde biletleri sold değerine ekler.

Sağlanan kod, kapasiteyi ve her satırda bir istenen bilet sayısını okur. Her biri için sold 3, left 7, invalid count, sold out veya only 2 left yazdırır.

Kodun TicketError.swift ve Seats.swift dosyalarına yazılmalıdır. main.swift, sağlanan giriş/çıkış kodunu içerir ve düzenlenemez.

Kendin dene

// Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
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 iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Swift playground