0

I'm trying to create a mock as shown below and getting the compile warning. Not sure what I'm doing wrong here. Or perhaps there's a different approach in creating this mock.

protocol Decodable {}

struct Action<D: Decodable> {}

protocol Requestable {
    func perform<T: Decodable>(action: Action<T>)
}

class MockRequestable<U: Decodable>: Requestable {
    var action: Action<U>!

    func perform<T: Decodable>(action: Action<T>) {
        self.action = action as? Action<U> 
        // Warning: Cast from 'Action<T>' to unrelated type 'Action<U>' always fails
    }
}
abc123
  • 8,043
  • 7
  • 49
  • 80
  • Generics are invariant – thus a `Action` is not an `Action`, even if a `T` is a `U`. See [How do I store a value of type Class in a Dictionary of type \[String:Class\] in Swift?](http://stackoverflow.com/q/38590548/2976878) & [Swift generic coercion misunderstanding](http://stackoverflow.com/q/41976844/2976878) – Hamish Feb 03 '17 at 23:31
  • Thanks for the links - after reading, it seems like the only way to do this is via Type Erasure in which case my `Action` struct and `perform` func would no longer be generic. `Action` would use the erased `AnyDecodable` - correct? – abc123 Feb 04 '17 at 14:07
  • I'm not sure entirely on what you're using `action` for, but given that it's a struct, simply converting it to an `Action` would work – depending on how `Action` is actually implemented. But yes, a type erasure should work too. – Hamish Feb 04 '17 at 22:36
  • Thanks @Hamish - I'm clear now. – abc123 Feb 05 '17 at 22:36

0 Answers0