gpt4 book ai didi

swift - 为什么我们不能转换为具有关联类型的协议(protocol)类型,而是使用泛型达到相同的效果?

转载 作者:搜寻专家 更新时间:2023-11-01 06:35:54 24 4
gpt4 key购买 nike

考虑这段代码:

extension Collection {
func foo() -> Int {
if self.first is Collection {
return (self.first as! Collection).underestimatedCount // ERROR
}
else {
return self.underestimatedCount
}
}
}

我们得到了可怕的和显然广泛令人费解的:

protocol 'Collection' can only be used as a generic constraint because it has Self or associated type requirements.

然而,这愉快地编译:

func foo<C: Collection>(_ c: C) -> Int where C.Iterator.Element: Collection {
if let first = c.first {
return first.underestimatedCount // *
} else {
return c.underestimatedCount
}
}

为什么?!

特别是,编译器不知道*first的相关类型(的类型)是如何实现的;它只会得到它们曾经存在的 promise (因为Collection 类型的任何对象必须 实现它们)。第一个例子中也有同样的保证!那么,为什么编译器会提示一个而不是另一个呢?

我的问题是:在 * 行,编译器知道什么它不在 ERROR 行?

最佳答案

协议(protocol)类型值使用“存在容器”表示(参见 this great WWDC talk ;或 on Youtube ),它由固定大小的值缓冲区组成,以便存储值(如果值大小超过这个,它会堆分配),一个指向协议(protocol)见证表的指针,以便查找方法实现和一个指向值见证表的指针,以便管理值的生命周期。

非专用泛型使用几乎相同的格式(我稍微深入一点 in this Q&A )——当它们被调用时,指向协议(protocol)和值见证表的指针被传递给函数,值本身是使用值缓冲区本地存储在函数内部,它将堆分配大于该缓冲区的值。

因此,由于它们的实现方式非常相似,我们可以得出结论,无法根据具有关联类型的协议(protocol)或 Self 进行对话。泛型之外的约束只是语言的当前限制。没有真正的技术原因说明它不可能,只是尚未实现(尚未)。

以下是关于“Generalized existentials”的泛型声明的摘录,其中讨论了这在实践中如何运作:

The restrictions on existential types came from an implementation limitation, but it is reasonable to allow a value of protocol type even when the protocol has Self constraints or associated types. For example, consider IteratorProtocol again and how it could be used as an existential:

protocol IteratorProtocol {
associatedtype Element
mutating func next() -> Element?
}

let it: IteratorProtocol = ...
it.next() // if this is permitted, it could return an "Any?", i.e., the existential that wraps the actual element

Additionally, it is reasonable to want to constrain the associated types of an existential, e.g., "a Sequence whose element type is String" could be expressed by putting a where clause into protocol<...> or Any<...> (per "Renaming protocol<...> to Any<...>"):

let strings: Any<Sequence where .Iterator.Element == String> = ["a", "b", "c"]

The leading . indicates that we're talking about the dynamic type, i.e., the Self type that's conforming to the Sequence protocol. There's no reason why we cannot support arbitrary where clauses within the Any<...>.

从能够将值键入为具有关联类型的协议(protocol),到允许类型转换为给定类型并因此允许像您的第一个扩展这样的东西进行编译只是一小步。

关于swift - 为什么我们不能转换为具有关联类型的协议(protocol)类型,而是使用泛型达到相同的效果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41695792/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com