Menu
Coddy logo textTech

Recap - Payment System

Part of the Object Oriented Programming section of Coddy's Swift journey. Lesson 31 of 57.

challenge icon

Challenge

Hard

Design a payment system with protocols. PaymentMethod requires name, fee(for amount: Int) -> Int and mutating func pay(_ amount: Int) -> Bool. A protocol extension provides total(for:) (amount plus fee). Implement Card (fee 2% rounded down, always succeeds, counts payments), Wallet (a stored balance, no fee, fails when the total is more than the balance, otherwise reduces it) and GiftCard (a stored balance, no fee, pays whatever it can: when the balance is too small it refuses). Complete checkout(_:with:), which tries each payment method in the given order and returns paid 100 with wallet (fee 0) for the first one that succeeds, or declined when none does. It also returns the updated methods so their balances carry over between purchases.

The supplied code reads a wallet balance and a gift card balance, then purchase amounts. For each purchase it tries gift card, wallet and card in that order and prints the result, then the final balances.

Your code goes in PaymentMethod.swift, Card.swift, Wallet.swift, GiftCard.swift and Functions.swift. main.swift holds the supplied input/output code and cannot be edited.

Try it yourself

// Supplied input/output code: keep it as it is
var input: [String] = []
while let line = readLine() { input.append(line) }
var methods: [any PaymentMethod] = [GiftCard(balance: Int(input[1])!), Wallet(balance: Int(input[0])!), Card()]
for line in input.dropFirst(2) {
    let (result, updated) = checkout(Int(line)!, with: methods)
    methods = updated
    print(result)
}
for m in methods {
    if let g = m as? GiftCard { print("gift card left \(g.balance)") }
    if let w = m as? Wallet { print("wallet left \(w.balance)") }
    if let c = m as? Card { print("card payments \(c.payments)") }
}

All lessons in Object Oriented Programming

Practice on your own: Swift playground