Extension

Extension เป็นการเพิ่มความสามารถให้ Class, Struct, Enum หรือ Protocol โดยที่เราไม่ต้องมีโค้ดของ type เหล่านั้น ทำให้เราก็สามารถเพิ่มความสามารถที่ต้องการให้กับ ไลบารีภายนอกได้ด้วย

ถ้าเราต้องการเพิ่ม compute property isOn เราทำได้แบบนี้

extension TapSwitch {
    var isOn: Bool {
        self == .on
    }
}

print(state.isOn)

บางครั้งเราเพิ่มความสามารถลงบน type standard อย่าง Double เพื่อทำ format หรือทำให้โค้ดเราอ่านง่ายขึ้นแบบนี้

extension Double {
    var km: Double { return self * 1_000.0 }
    var m: Double { return self }
    var cm: Double { return self / 100.0 }
    var mm: Double { return self / 1_000.0 }
    var ft: Double { return self / 3.28084 }
}

let distance = 45.km + 5.cm

หรือเราสามารถทำให้ TapSwitch สามารถ conform protocol ได้แบบนี้

enum TapSwitch {
    case on
    case off
}

extension TapSwitch: ItemDiscribable {
    var description: String {
        switch self {
        case .on: return "current is on"
        case .off: return "current is off"
        }
    }
}

extension TapSwitch: Togglable {
    mutating func toggle() {
        switch self {
        case .on:
            self = .off
        case .off:
            self = .on
        }
    }
}

Extension สามารถเพิ่มความสามารถได้ แต่จะไม่สามารถ override ได้

รวมทั้งไม่สามารถเก็บค่าไว้ได้ เราไม่สามารถประกาศ ตัวแปรเพิ่มโดยไม่ใช่ compute properties ได้

จากตอนที่เราเขียน Enum เราจะไม่สามารถเขียนให้เป็น raw type และใช้ case argument ไปพร้อม ๆ กันได้

enum PaymentType: String {
    case cheque(issuer:String)
    case creditCard(number:String)
}
// ใช้ case argument และต้องการเป็น raw type String
// โปรแกรมจะไม่สามารถรันได้

เราสามารถนำ extension มาเพิ่มความสามารถให้กับ enum ที่เป็น case argument ทำให้สามารถเป็น raw type ได้ แบบนี้

enum PaymentType {
    case cheque(issuer:String)
    case creditCard(number:String)

    var description: String {
        switch self {
        case let .cheque(issuer): return "Cheque issued by \(issuer)"
        case let .creditCard(number): return "Credit card number \(number)"
        }
    }
}

extension PaymentType: RawRepresentable {
    typealias RawValue = String

    init?(rawValue: RawValue) {
        switch rawValue {
        case "Cheque": self = .cheque(issuer: "")
        case "CreditCard": self = .creditCard(number: "")
        default: return nil
        }
    }

    var rawValue: String {
        return description
    }
}

เราเพิ่ม extension ให้ enum conform RawRepresentable จากนั้นเราก็ implement protocol requirement ใน extension ก็จะทำให้เราสามารถใช้งานได้

Last updated