Swift:泛型和类型约束,奇怪的行为

时间:2016-01-25 13:23:13

标签: swift

我无法弄清楚如何进行演员表演,这会让我最终引入一些与泛型一起工作的动态。

下一段代码无法编译。它显示了这个错误:

  

无法调用' createContainer'使用类型的参数列表   '(FooProtocol)'预期类型'(T)'

的参数列表
protocol FooProtocol {
    func doSomething()
}

class Foo : FooProtocol {
    func doSomething() {}
}

class Container<T : FooProtocol> {
    let someDataConformingFooProtocol : T

    init(someDataConformingFooProtocol : T) {
        self.someDataConformingFooProtocol = someDataConformingFooProtocol
    }
}

class AllTogether {

    init () {
        createContainer(Foo()) //So far, so good

        let foo2Mask : AnyObject = Foo()
        if let foo2MaskChecked = foo2Mask as? FooProtocol {
            createContainer(foo2MaskChecked)
            //ERROR: Cannot invoke 'createContainer' with an argument list of type '(FooProtocol)'
            //Expected an argument list of type '(T)'
        }

    }

    func createContainer<T : FooProtocol>(data: T){
        Container<T>(someDataConformingFooProtocol: data)
    }
}

这真的是预期的行为吗?因为我个人无法理解编译器抱怨它的原因或原因。

什么是合适的演员?没有引用具体类,我的意思是不喜欢这个:

if let foo2MaskChecked = foo2Mask as? Foo 

谢谢!

1 个答案:

答案 0 :(得分:0)

归结为@Hamish在评论中提到的T: FooProtocolFooProtocol之间的区别。

当我有这样的功能时:

func foo(_ i: FooProtocol)

我要使用类型为FooProtocol的实例,因此我可以传入一个符合FooProtocol或它的类型为FooProtocol的值。这类似于子类化,在子类化中,您可以将SuperClassSubClass都传递到SuperClass中。

但是,如果您具有这样的功能:

func foo<T>(_ i: T) where T: FooProtocol

我可以传入任何符合FooProtocol的类型,但是由于FootProtocol不符合自身,因此您不能将其传入。

因此,在您的问题中,您尝试传递类型FooProtocol,其中类型必须符合FooProtocol。您可以通过以下方法解决此问题:

class Container {
    let someDataConformingFooProtocol: FooProtocol

    init(someDataConformingFooProtocol: FooProtocol) {
        self.someDataConformingFooProtocol = someDataConformingFooProtocol
    }
}

// Later
func createContainer(data: FooProtocol){
    Container(someDataConformingFooProtocol: data)
}