在协议中引用无效的关联类型导致的神秘错误

问题描述

在线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

请帮助我找出以上代码中出了什么问题。非常感谢!

解决方法

此代码有很多错误。

  1. SparrowCanary被声明为符合Flier,但是没有说出它们各自的Other类型是什么。

  2. 您正在尝试将parrotcanary都传递给sparrow.flockTogether(with:)sparrow.sing(with:),但是这些方法仅接受一种类型的对象-{{ 1}}。以上几点说明,您可能会误解什么是关联类型。我建议您read about them

  3. 您正在尝试访问不一定存在的内容,例如Sparrow.Otherf.name。回想一下f.sing()f,它不受任何类型的限制,因此它可以是 任何 。而且“任何内容”都不会总是带有Other供您访问。

我建议采取以下措施使呼叫者正常工作:

  1. 删除关联的类型,改用通用方法。如果调用方决定传递nameParrot,则关联类型是不合适的。

  2. Canaryname添加到sing(),以便编译器知道符合Flier的任何对象都有那些成员。如果然后将Flier(上述通用方法的通用参数)约束为Other,那么我们可以毫无问题地访问Fliersing()

现在的固定代码如下:

name

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...