robnik
1
I create two protocols:
protocol Payment {
var productIdentifier: String { get }
var quantity: Int { get }
}
protocol Transaction {
var payment: Payment { get }
}
Then I try to make the StoreKit classes conform, like this:
extension SKPayment: Payment { } // compiler okay with this
extension SKPaymentTransaction: Transaction { } // error here
The compiler wants me to add the var payment: Payment to make SKPaymentTransaction conform to Transaction. But SKPaymentTransaction already has a property called payment. It's an SKPayment, which I've declared is a Payment. It seems like the compiler could accept this. It's logically sound (or am I missing something?).
It would make sense to disallow it, if SKPaymentTransaction.payment were settable.
I think if the compiler understood covariance here it would accept it. (?)
I can't implement it explicitly either, because I can't write:
var payment: Payment {
return self.payment // infinite recursion
}
Nevin
2
Are you sure this is the design you want, and not eg. an associatedtype for Transaction.Payment?
If you are absolutely certain that the existential is what you want, you could use the unofficial attribute @_implements.
1 Like
robnik
3
Wow, didn't know about @_implements, thanks!
I tried associated types first, but I didn't like how it was then forcing everything to become generic. Now I'm thinking it's a more accurate design and need to try that again. I have a class called StoreHelp that is a facade to in-app purchase stuff. I pass it a parameter that conforms to protocol StoreAPI, which would be either the real app store, or a mock for testing. And that protocol uses the Transaction and Payment protocols from my question. If StoreAPI has associated types for Payment and Transaction, then maybe I need to create some of those manual existential types (AnyStoreAPI) to pass around, so that not everything that touches it has to have generic type args. ?