提问人:Michael May 提问时间:10/17/2020 更新时间:10/17/2020 访问量:839
由于在协议中引用无效关联类型而导致的神秘错误
Mysterious error caused by reference to invalid associated type in protocol
问:
在线 Swift 5.1 编译器编译以下代码并报告错误。最重要的一个如下:
main.swift:18:23: error: reference to invalid associated type 'Other' of type 'Sparrow'
func sing(with f: Other) {
^
Stackoverflow 上的另一个线程提出了一个更复杂的问题。(引用类型为“DecodedArray<T>”的无效关联类型“Iterator”)。目前还没有关于该线程的答案。
我的案例代码和编译器报告的错误的完整列表如下所示:
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
您正在尝试将 a 和 a 传递给 和 ,但这些方法只接受一种类型的对象 - 。这一点以及上面的一点表明,您可能误解了什么是关联类型。我建议你阅读它们。
parrot
canary
sparrow.flockTogether(with:)
sparrow.sing(with:)
Sparrow.Other
您正在尝试访问不一定存在的内容,例如 和 。回想一下,这是一个 ,它不受任何类型的约束,因此它可以是任何类型。而且“任何东西”并不总是有可供您访问的。
f.name
f.sing()
f
Other
name
我建议采取以下措施使调用方工作:
删除关联的类型并改用泛型方法。如果调用方决定是否传入 或 .
Parrot
Canary
添加 and,以便编译器知道任何符合的内容都具有这些成员。如果我们随后将(上述泛型方法的泛型参数)限制为 ,那么我们可以毫无问题地访问。
name
sing()
Flier
Flier
Other
Flier
sing()
name
也符合
Parrot
Flier
修复后的代码现在如下所示:
protocol Flier {
var name: String { get }
func flockTogether<Other: Flier>(with f:Other)
func sing<Other: Flier>(with f:Other)
func sing()
}
struct Sparrow : Flier {
let name: String
init (_ name: String) {
self.name = name
}
func flockTogether<Other: Flier>(with f:Other) {
print("Birds, \(name), and \(f.name), of a feather flock together.")
}
func sing<Other: Flier>(with f:Other) {
sing()
f.sing()
}
func sing () {
print("Sparrow sings \"chirp, chirp\"!")
}
}
struct Parrot : Flier{
func flockTogether<Other>(with f: Other) where Other : Flier { }
func sing<Other>(with f: Other) where Other : Flier { }
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<Other: Flier>(with f:Other) {}
func sing<Other: Flier>(with f:Other) {}
func sing () {
print("Canary sings \"tweet, tweet\"!")
}
}
上一个:Java 解析 XML
评论
protocol Flier {
var name: String { get }
func flockTogether<Other: Flier>(with f: Other)
func sing<Other: Flier>(with f: Other)
func sing()
}