我对于用于协议的关联类型的语法与另一方面的通用类型之间的区别感到困惑。
例如,在Swift中,可以使用类似的方法定义一个通用类型
struct Stack<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
而一个使用类似的东西来定义一个具有关联类型的协议
protocol Container {
typealias 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 }
}
有没有一些深刻的(或者也许只是显而易见,迷失在我身上),因为语言没有采用后一种语法?
这已经在devlist上被覆盖了几次。基本的答案是相关类型比类型参数更灵活。虽然这里有一个类型参数的具体情况,但很有可能有几个参数。例如,Collections有一个Element类型,而且还有一个Index类型和一个Generator类型。如果您使用类型参数化完全专门化,那么您必须谈论Array< String,Int,Generator&String>>或类似物。
可以跳过所有这些(Java做),但是你有更少的方法来限制你的类型。 Java实际上在限制类型方面是非常有限的。您不能在Java中的集合上使用任意索引类型。 Scala扩展了类似于Swift的关联类型的java类型系统。相关类型在Scala中非常强大。它们也是混乱和脱发的常规来源。
这个额外的力量是否值得吗是一个完全不同的问题,只有时间会告诉你。但相关类型绝对比简单类型参数化更强大。