[swift-users] The case of broken polymorphism or "Cannot convert value of type to expected argument type"?
Isaac Rivera
developer at isaacrivera.com
Mon Feb 20 03:37:20 CST 2017
I can see it is a (counter-intuitive) language design decision for type safety… but then why, in the code below I can:
class OtherThing: Something<UIViewController> {
override func start(_ completion: SomeCallback? = nil) {
// implementation details...
}
}
let firstThing = OtherThing(viewController: UINavigationController())
OtherThing extends Something<UIViewController>… but I can instantiate it with the subtype…
Ok you will say, UINavigationController is a subtype of UIViewController, but that still does not make Something<UINavigationController> a subtype of Something<UIViewController>.
Fair enough, but:
let c1: Something<UIViewController> = Something(viewController: UINavigationController())
// c1 is of type "Something<UIViewController>"
let c2 = Something(viewController: UINavigationController())
// c1 is of type "Something<UINavigationController>”
So it appears Something<UINavigationController> can be cast to type Something<UIViewController>…
Yet this is illegal?
let somethings: [Something<UIViewController>] = [c1, c2]
I dont know, something seems inconsistent.
> On Feb 16, 2017, at 10:59 PM, Slava Pestov <spestov at apple.com> wrote:
>
> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20170220/c55a2ec3/attachment.html>
More information about the swift-users
mailing list