Search code examples
iosswiftnetwork-programmingprotocolsencodable

Protocol with Encodable protocol


I have struct that has parameter with protocol type

protocol CheckoutOrder {}

struct CheckoutOrderEntity: Encodable {
    private enum CodingKeys: String, CodingKey {
        case amount
        case payment
    }
    
    let amount: Int
    let payment: CheckoutOrder
}

Also have 2 structs which implements protocol CheckoutOrder

struct ApplePayOrderEntity: Encodable {
    private enum CodingKeys: String, CodingKey {
        case token
    }
    
    let token: ApplePayTokenEntity
}

extension ApplePayOrderEntity: CheckoutOrder { }
struct CheckoutPaymentEntity: Encodable {
    private enum CodingKeys: String, CodingKey {
        case terminalName
        case shouldUseBalance
    }
    
    let shouldUseBalance: Bool
    let terminalName: String
}

extension CheckoutPaymentEntity: CheckoutOrder { }

I have an error: Type 'CheckoutOrderEntity' does not conform to protocol 'Encodable' and CheckoutOrder protocol requires function 'encode(to:)'.... So, the main reason of using protocol is that payment can be type of ApplePayOrderEntity or CheckoutPaymentEntity. How to solve problem or what is best practice in this case?


Solution

  • First you need to make the protocol extend Encodable to tell the compiler that anything that conforms to CheckoutOrder also conforms to Encodable

    protocol CheckoutOrder: Encodable {}
    

    Then I would use generics for this and change CheckoutOrderEntity to

    struct CheckoutOrderEntity<Payment: CheckoutOrder>: Encodable {
        private enum CodingKeys: String, CodingKey {
            case amount
            case payment
        }
    
        let amount: Int
        let payment: Payment
    }
    

    Example

    let checkout = CheckoutOrderEntity(amount: 1000,
                                       payment: CheckoutPaymentEntity(shouldUseBalance: true,
                                                                      terminalName: "terminal"))