# Extension

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

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

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

print(state.isOn)
```

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

```swift
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 ได้แบบนี้

```swift
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
        }
    }
}
```

{% hint style="info" %}
`Extension` สามารถเพิ่มความสามารถได้ แต่จะไม่สามารถ `override` ได้

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

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

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

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

```swift
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 ก็จะทำให้เราสามารถใช้งานได้


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://pakornpat.gitbook.io/ios-app/swift/extension.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
