问题描述
我对协议的关联类型使用的语法和另一方面的泛型类型之间的区别感到困惑.
I'm confused about the difference between the syntax used for associated types for protocols, on the one hand, and generic types on the other.
例如,在 Swift 中,可以使用类似的东西来定义泛型类型
In Swift, for example, one can define a generic type using something like
struct Stack<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
虽然人们使用类似的东西定义了具有关联类型的协议
while one defines a protocol with associated types using something like
protocol Container {
associatedtype T
mutating func append(item: T)
var count: Int { get }
subscript(i: Int) -> T { get }
}
为什么不只是后者:
protocol Container<T> {
mutating func append(item: T)
var count: Int { get }
subscript(i: Int) -> T { get }
}
该语言没有采用后一种语法是否有一些深刻的(或者可能只是显而易见的,但我已经忘记了)原因?
Is there some deep (or perhaps just obvious and lost on me) reason that the language hasn't adopted the latter syntax?
推荐答案
这已在 devlist 中多次提及.基本答案是关联类型比类型参数更灵活.虽然这里有一个类型参数的特定情况,但很可能有几个.例如,集合有一个元素类型,还有一个索引类型和一个生成器类型.如果你完全用类型参数化来专门化它们,你就必须谈论诸如 Array>
之类的东西.(这将允许我创建以 Int 以外的东西作为下标的数组,这可以被视为一个特性,但也会增加很多复杂性.)
This has been covered a few times on the devlist. The basic answer is that associated types are more flexible than type parameters. While you have a specific case here of one type parameter, it is quite possible to have several. For instance, Collections have an Element type, but also an Index type and a Generator type. If you specialized them entirely with type parameterization, you'd have to talk about things like Array<String, Int, Generator<String>>
or the like. (This would allow me to create arrays that were subscripted by something other than Int, which could be considered a feature, but also adds a lot of complexity.)
可以跳过所有这些(Java 会这样做),但是您可以限制类型的方法较少.实际上,Java 在约束类型方面非常有限.在 Java 中,您的集合不能具有任意索引类型.Scala 使用关联类型扩展了 Java 类型系统,就像 Swift 一样.关联类型在 Scala 中非常强大.它们也是造成困惑和脱发的常见原因.
It's possible to skip all that (Java does), but then you have fewer ways that you can constrain your types. Java in fact is pretty limited in how it can constrain types. You can't have an arbitrary indexing type on your collections in Java. Scala extends the Java type system with associated types just like Swift. Associated types have been incredibly powerful in Scala. They are also a regular source of confusion and hair-tearing.
这种额外的力量是否值得是一个完全不同的问题,只有时间会证明.但是关联类型肯定比简单的类型参数化更强大.
Whether this extra power is worth it is a completely different question, and only time will tell. But associated types definitely are more powerful than simple type parameterization.
这篇关于为什么协议的关联类型不在 Swift 中使用泛型类型语法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!