无法将泛型类型的值转换为关联类型的预期参数

时间:2017-03-09 13:23:50

标签: ios swift generics swift3

说我有协议:

protocol Foo:Hashable, Comparable {}

一个将这个人作为通用的结构:

struct UsingFoo<T:Foo> {}

到目前为止一切顺利。假设我想在第二个协议上使用Foo

protocol Bar {
    associatedtype FooType:Foo
    func doSomething(with:UsingFoo<FooType>)
}

在课堂上使用Bar:

class UsingBar<F:Foo>:Bar {
    typealias FooType = F
    func doSomething(with: UsingFoo<F>) {}
}

现在说我想带这些家伙参加派对:

class FooBarParty<F:Foo, B:Bar>: NSObject {
    var b:B
    init(b:B) {
        self.b = b
        // interestingly, this line below won't compile
        // self.b = UsingBar<F>.init()
    }

    func thisWillCompile () {
        UsingBar<F>.init().doSomething(with: UsingFoo<F>.init())
    }

    func thisWontCompile() {
        b.doSomething(with: UsingFoo<F>.init())
    }

    func thisAlsoWont (anotherB:B) {
        anotherB.doSomething(with: UsingFoo<F>.init())
    }
}

编译器说:

Cannot convert value of type 'UsingFoo<F>' to expected argument type 'UsingFoo<_>'

问题是:我怎样才能使用Bar类型的属性?一如既往,任何评论都非常赞赏

编辑:由于接受了答案,我发现我应该指定FooType。它看起来像这样:

class FooBarParty<F:Foo, B:Bar> where B.FooType == F { ... }

1 个答案:

答案 0 :(得分:1)

所以这里的问题主要是:

  

为什么我不能使用B的实例来呼叫doSomething(UsingFoo<F>()),但我可以使用UsingBar<F>的实例

问题在于您的关联类型 - FooType

doSomething方法表示它只接受UsingFoo<FooType>类型的参数。我们知道在UsingBar<F>中,FooTypeF。因此UsingBar<F>().doSomething需要UsingFoo<F>。在thisWillCompile中,您可以给它UsingFoo<F>!它有效!

现在,您将获得B的另一个随机实例并致电doSomething。它需要什么样的论据?你可能会说UsingFoo<FooType>。嗯,这里的FooType是什么?我们不知道!如果我们在此处添加此扩展程序,则可以是FString

extension String: Foo { }

FooType可以是实现Foo的任何内容。它不需要F。但是你传给它UsingFoo<F>。这就是为什么它不起作用的原因!

正如你所说,这条线也不起作用:

self.b = UsingBar<F>.init()

您需要注意B 不是 Bar。它可以是实现Bar的任何类型,不一定是UsingBar<F>。你正在做的事情基本上是:

class A {}
class B: A {}
class C: A {}
let obj: B = C()

这就是为什么不编译。