On Mon, 20 Feb 2017 at 8:38 pm, Isaac Rivera via swift-users < swift-users@swift.org> wrote:
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@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>.
Covariance and contravariance (computer science) - Wikipedia
Slava
On Feb 16, 2017, at 9:05 AM, Isaac Rivera via swift-users < > swift-users@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@swift.org
https://lists.swift.org/mailman/listinfo/swift-users
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users