说我有协议:
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 { ... }
答案 0 :(得分:1)
所以这里的问题主要是:
为什么我不能使用
B
的实例来呼叫doSomething(UsingFoo<F>())
,但我可以使用UsingBar<F>
的实例
问题在于您的关联类型 - FooType
。
doSomething
方法表示它只接受UsingFoo<FooType>
类型的参数。我们知道在UsingBar<F>
中,FooType
是F
。因此UsingBar<F>().doSomething
需要UsingFoo<F>
。在thisWillCompile
中,您可以给它UsingFoo<F>
!它有效!
现在,您将获得B
的另一个随机实例并致电doSomething
。它需要什么样的论据?你可能会说UsingFoo<FooType>
。嗯,这里的FooType
是什么?我们不知道!如果我们在此处添加此扩展程序,则可以是F
或String
:
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()
这就是为什么不编译。