问题描述
在线Swift 5.1编译器会编译以下代码并报告错误。最重要的陈述如下:
main.swift:18:23: error: reference to invalid associated type 'Other' of type 'Sparrow'
func sing(with f: Other) {
^
Stackoverflow上的另一个线程在更复杂的情况下也出现了相同的问题。 (Reference to invalid associated type 'Iterator' of type 'DecodedArray<T>')。该线程还没有答案。
我的案例代码和编译器报告的错误的完整列表如下所示:
protocol Flier {
associatedtype Other
func flockTogether(with f:Other)
func sing(with f:Other)
}
struct Sparrow : Flier {
let name: String
init (_ name: String) {
self.name = name
}
func flockTogether(with f: Other) {
print("Birds,\(name),and \(f.name),of a feather flock together.")
}
func sing(with f: Other) {
sing()
f.sing()
}
func sing () {
print("Sparrow sings \"chirp,chirp\"!")
}
}
struct Parrot {
let name: String
init (_ name: String) {
self.name = name
}
func sing () {
print("Parrot sings \"chuck,chuck\"!")
}
}
struct Canary: Flier {
let name: String
init (_ name: String) {
self.name = name
}
func flockTogether(with f: Other) {}
func sing(with f: Other) {}
func sing () {
print("Canary sings \"tweet,tweet\"!")
}
}
let sparrow = Sparrow("sparrow")
let parrot = Parrot("parrot")
let canary = Canary("canary")
sparrow.flockTogether(with: parrot)
sparrow.sing(with: parrot)
sparrow.flockTogether(with: canary)
sparrow.sing(with: canary)
编译器报告的错误:
main.swift:18:23: error: reference to invalid associated type 'Other' of type 'Sparrow'
func sing(with f: Other) {
^
main.swift:8:8: error: type 'Sparrow' does not conform to protocol 'Flier'
struct Sparrow : Flier {
^
main.swift:2:20: note: protocol requires nested type 'Other'; do you want to add it?
associatedtype Other
^
main.swift:38:8: error: type 'Canary' does not conform to protocol 'Flier'
struct Canary: Flier {
^
main.swift:2:20: note: protocol requires nested type 'Other'; do you want to add it?
associatedtype Other
^
compiler exit status 1
请帮助我找出以上代码中出了什么问题。非常感谢!
解决方法
此代码有很多错误。
-
Sparrow
和Canary
被声明为符合Flier
,但是没有说出它们各自的Other
类型是什么。 -
您正在尝试将
parrot
和canary
都传递给sparrow.flockTogether(with:)
和sparrow.sing(with:)
,但是这些方法仅接受一种类型的对象-{{ 1}}。以上几点说明,您可能会误解什么是关联类型。我建议您read about them。 -
您正在尝试访问不一定存在的内容,例如
Sparrow.Other
和f.name
。回想一下f.sing()
是f
,它不受任何类型的限制,因此它可以是 任何 。而且“任何内容”都不会总是带有Other
供您访问。
我建议采取以下措施使呼叫者正常工作:
-
删除关联的类型,改用通用方法。如果调用方决定传递
name
或Parrot
,则关联类型是不合适的。 -
将
Canary
和name
添加到sing()
,以便编译器知道符合Flier
的任何对象都有那些成员。如果然后将Flier
(上述通用方法的通用参数)约束为Other
,那么我们可以毫无问题地访问Flier
和sing()
。
现在的固定代码如下:
name