[swift-users] The case of broken polymorphism or "Cannot convert value of type to expected argument type"?
Slava Pestov
spestov at apple.com
Thu Feb 16 21:59:55 CST 2017
Hi Isaac,
This is not about associated types. Rather, the issue is that a ‘Thing’ is a ‘Something<UINavigationController>’, but you are casting it to ‘Something<UIViewController>’. The two types are not related; in general, if A is a subtype of B, then G<A> is not a subtype of G<B>.
https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
Slava
> On Feb 16, 2017, at 9:05 AM, Isaac Rivera via swift-users <swift-users at swift.org> wrote:
>
> Hello, list!
>
> I am trying to find my way around Swift’s protocol limitations. It appears that in general, any protocol with declared associatedtype will break polymorphism?
>
> Take the case below which does not compile. All "Thing” instances are "Something<VC: UIViewController>” but they can’t be passed around or coerced as so.
>
> How is it that I can legally write the code:
>
> class Thing: Something<UINavigationController> { }
>
> and instantiate it, but it is not the very thing it implements?
>
> All Thing instances conform to the public interfaces of Something<UIViewController> so why can’t they be recognized as such and coerced as such?
>
> What is the work-around of this break in Polymorphism?
>
> import UIKit
>
> protocol Anything: class, NSObjectProtocol {
>
> associatedtype ViewControllerType: UIViewController
>
> var viewController: ViewControllerType { get }
>
> init(viewController: ViewControllerType)
>
> func addAnything(anything: Something<UIViewController>) -> Bool
> }
>
> class Something<VC: UIViewController>: NSObject, Anything {
>
> typealias ViewControllerType = VC
>
> private(set) var viewController: ViewControllerType
>
> required init(viewController: ViewControllerType) { self.viewController = viewController }
>
> final private var things = [String: Something<UIViewController>]()
>
> final internal func addAnything(anything: Something<UIViewController>) -> Bool {
> // implementation details...
> return true
> }
> }
>
> class Thing: Something<UINavigationController> { }
>
> let firstThing = Thing(viewController: UINavigationController())
> let secondThing = Thing(viewController: UINavigationController())
>
> firstThing.addAnything(anything: secondThing)
>
> // Playground execution failed: error: MyPlayground.playground:48:34: error: cannot convert value of type 'Thing' to expected argument type 'Something<UIViewController>'
>
> firstThing.addAnything(anything: secondThing as Something<UIViewController>)
>
> // Playground execution failed: error: MyPlayground.playground:48:34: error: cannot convert value of type 'Thing' to type 'Something<UIViewController>' in coercion
>
>
>
>
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
More information about the swift-users
mailing list