본문은 야곰 아카데미 커리어 스타터 캠프를 통해 학습한 내용을 회고한 글입니다.

Protocol Oriented Programming
STEP01
main과 Chargeable 소스파일을 만든 후 commit해준다. main.swift:
typealias WattPerHour = Int
typealias Watt = IntChargeable.swift:
protocol Chargeable {
    var maximumWattPerHour: WattPerHour { get set }
    
    func convert(chargeableWattPerHour: WattPerHour) -> WattPerHour
}그리고 STEP01을 commit 해준다. commit 해주기 이전에 POPExercise.xcodeproj파일이 자꾸 commit 되려고 해서 fork에서 이 부분 역시 ignore 처리 해주었다:

STEP02
feat-MacBook, feat-charger라는 이름의 브랜치를 각각 생성해준다:

요구사항에는 Charger를 구조체로 구현하라고 되어있었지만, enum으로 한 번 구현해봤다. Charger 열거형의 코드:
enum Charger: Chargeable, Portable {
    case appleWatchCharger
    case iphoneFastCharger
    case ipadCharger
    case macBookCharger
    case macBookFastCharger
    
    var name: String {
        switch self {
        case .appleWatchCharger:
            return "5Wh 애플워치 충전기"
        case .iphoneFastCharger:
            return "18Wh 아이폰 고속 충전기"
        case .ipadCharger:
            return "30Wh 아이패드 충전기"
        case .macBookCharger:
            return "96Wh 맥북 충전기"
        case .macBookFastCharger:
            return "106Wh 맥북 충전기"
        }
    }
    
    var maximumWattPerHour: WattPerHour {
        switch self {
        case .appleWatchCharger:
            return 5
        case .iphoneFastCharger:
            return 18
        case .ipadCharger:
            return 30
        case .macBookCharger:
            return 96
        case .macBookFastCharger:
            return 106
        }
    }
    
    func convert(chargeableWattPerHour: WattPerHour) -> WattPerHour {
        return min(chargeableWattPerHour, maximumWattPerHour)
    }
}MacBook 구조체의 코드:
import Foundation
struct MacBook: Portable {
    let name: String
    let maximumWattPerHour: WattPerHour
    var currentBattery: Watt {
        didSet {
            print("현재 저장된 배터리는 \(currentBattery)W입니다.")
        }
    }
    let maximumBattery: Watt
    
    init(name: String, maximumWattPerHour: Int, currentBattery: Int, maximumBattery: Int = 100) {
        self.name = name
        self.maximumWattPerHour = maximumWattPerHour
        self.currentBattery = currentBattery
        self.maximumBattery = maximumBattery
    }
    
    mutating func chargeBattery(charger: Chargeable) {
        print("\(name)을/를 충전합니다.")
        print("충전 중...")
        let chargeTime = calculateChargingTime(charger: charger)
        let formattedChargeTime = String(format: "%.2f", chargeTime)
        
        print("기존 저장된 배터리는 \(currentBattery)W였으며, \(charger.name)을 사용하여 완충까지 \(formattedChargeTime)시간 걸렸습니다.")
        
        currentBattery = maximumBattery
    }
    
    func calculateChargingTime(charger: Chargeable) -> Double {
        let batteryToBeCharged = maximumBattery - currentBattery
        let chargeTime = Double(batteryToBeCharged) / Double(charger.convert(chargeableWattPerHour: maximumWattPerHour))
        
        return chargeTime
    }
}각각의 코드를 xcodeproj 파일 없이 stage에 올린 후 각각 commit해준다. 그리고 둘 다 commit이 되면 메인이 될 브랜치에 merge해준다.
step03
가방에 물건을 넣는 프로토콜을 채택해주면 된다
Portable프로토콜의 코드:
protocol Portable {
    var name: String { get }
}
struct Bag {
    private var items: [Portable] = [] {
        didSet {
            print("가방에 \(items.last?.name ?? "물건")을/를 넣었습니다.")
        }
    }
    
    mutating func put(item: Portable...) {
        item.forEach { item in
            items.append(item)
        }
    }
}완성된 코드가 돌아가는 모습이다:

POP의 매커니즘
구체적인 타입이 아닌 추상화된 프로토콜을 통해 내부 구현을 숨긴다는 것이 이번 주차 학습의 핵심이었다고 볼 수 있다.
func calculateChargingTime(charger: Chargeable) -> Double {
    ...
}위의 코드처럼 매개변수로 프로토콜을 받는 것이 그 사례라고 볼 수 있다.
'YAGOM CAREER STARTER' 카테고리의 다른 글
| [CODE STARTER 복습] 20230317: week01 (0) | 2023.03.17 | 
|---|---|
| [TIL] 20230314: wait()/notify(queue:) (0) | 2023.03.14 | 
| [TIL] 20230309: Sync/Async/Blocking/Non-Blocking (0) | 2023.03.09 | 
| [TIL] 20230307: 동기/비동기/직렬/동시성, DispatchQueue (0) | 2023.03.07 | 
| [TIL] 20230303: 프로토콜로 id 지정하기 (0) | 2023.03.04 | 
 
                    
                   
                    
                   
                    
                  