协议中引用无效关联类型导致的神秘错误
Mysterious error caused by reference to invalid associated type in protocol
在线Swift5.1编译器编译如下代码报错。最重要的陈述如下:
main.swift:18:23: error: reference to invalid associated type 'Other' of type 'Sparrow'
func sing(with f: Other) {
^
Whosebug 上的另一个线程提出了同样的问题,但情况更复杂。 (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:)
,但这些方法只接受一种类型的对象 - Sparrow.Other
。这一点以及以上一点表明您可能误解了关联类型是什么。我建议你 read about them.
您正在尝试访问不一定存在的内容,例如 f.name
和 f.sing()
。回想一下 f
是一个 Other
,它不受任何类型的限制,因此它可以是 anything。而“任何东西”并不总是有一个 name
供您访问。
我建议以下方法使呼叫者正常工作:
删除关联类型并改用泛型方法。如果调用者要决定是传入 Parrot
还是 Canary
.
,则关联类型是不合适的
将 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\"!")
}
}
在线Swift5.1编译器编译如下代码报错。最重要的陈述如下:
main.swift:18:23: error: reference to invalid associated type 'Other' of type 'Sparrow'
func sing(with f: Other) {
^
Whosebug 上的另一个线程提出了同样的问题,但情况更复杂。 (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:)
,但这些方法只接受一种类型的对象 -Sparrow.Other
。这一点以及以上一点表明您可能误解了关联类型是什么。我建议你 read about them.您正在尝试访问不一定存在的内容,例如
f.name
和f.sing()
。回想一下f
是一个Other
,它不受任何类型的限制,因此它可以是 anything。而“任何东西”并不总是有一个name
供您访问。
我建议以下方法使呼叫者正常工作:
删除关联类型并改用泛型方法。如果调用者要决定是传入
,则关联类型是不合适的Parrot
还是Canary
.将
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\"!")
}
}