本文介绍了为什么协议的关联类型在Swift中使用泛型类型语法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对用于协议的关联类型的语法和另一种类型的泛型类型之间的区别感到困惑。



在Swift中,例如,可以使用类似于以下内容的类型定义泛型类型:

pre $ struct Stack< T> {
var items = [T]()
mutating func push(item:T){
items.append(item)
}
mutating func pop() - > T {
return items.removeLast()
}
}

而一个定义协议与相关类型使用类似于

 协议容器{
typealias T
变异func append(item:T)
var count:Int {get}
下标(i:Int) - > T {get}
}

为什么不只是后者:

  protocol Container< T> {
mutating func append(item:T)
var count:Int {get}
下标(i:Int) - > T {get}
}

有没有深度的我)原因,该语言没有采用后者的语法?

解决方案

这已经在devlist上覆盖了几次。基本答案是关联类型比类型参数更灵活。虽然这里有一个特定的参数类型,但很可能有几个参数。例如,集合有一个元素类型,但也是一个索引类型和一个生成器类型。如果你完全用类型参数化来完成它们的专门化,那么你必须讨论诸如数组< String,Int,Generator< String>> 之类的东西。



可以跳过所有这些(Java),但是你可以通过更少的方法限制类型。事实上Java在限制类型方面相当有限。 Java中的集合不能有任意的索引类型。 Scala使用类似Swift的关联类型来扩展Java类型系统。在Scala中,相关类型已经非常强大。这些额外的力量是否值得它是一个完全不同的问题,只有时间才能说明问题。但关联类型绝对比简单类型参数化更强大。


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.

In Swift, for example, one can defines 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 {
    typealias T
    mutating func append(item: T)
    var count: Int { get }
    subscript(i: Int) -> T { get }
}

Why isn't the latter just:

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?

解决方案

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.

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中使用泛型类型语法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 03:58