我对一方面用于协议的关联类型的语法和另一方面用于泛型类型的语法之间的区别感到困惑。
例如,在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 }
}
是否有某种深层的原因(或者也许是显而易见的,对我来说就迷失了),原因是该语言未采用后一种语法?
在开发人员列表中已对此进行了多次讨论。基本答案是关联类型比类型参数更灵活。虽然您在这里有一个类型参数的特定情况,但很可能会有多个。例如,集合具有元素类型,但也具有索引类型和生成器类型。如果您完全使用类型参数化对它们进行专门化,则您必须谈论诸如此类Array<String, Int, Generator<String>>
的事情。(这将允许我创建由Int以外的其他元素下标的数组,该数组可以被认为是一个功能,但同时也增加了很多复杂性。)
可以跳过所有操作(Java可以这样做),但是然后您可以使用更少的方法来约束类型。实际上,Java在限制类型方面非常有限。在Java中,您的集合不能具有任意索引类型。Scala像Swift一样,通过关联类型扩展了Java类型系统。关联类型在Scala中非常强大。它们也是造成混乱和头发折磨的常见原因。
这种额外的功能是否值得,是一个完全不同的问题,只有时间才能证明。但是关联类型肯定比简单类型参数化更强大。
问题内容: 我有一个协议,该协议继承自另一个协议,并且满足扩展要求。 还有另一种协议,其要求()应该为。 现在,如果我尝试使用as ,那么它将无法编译。它说, 推断的类型“地址”(通过匹配要求“ valueForDetail”)无效:不符合“ Validator”。 这种用法非法吗?我们不能像所有的那样用它代替。 下面是我正在尝试的代码。 更新: 提交了一个错误。 问题答案: David已经提到的
问题内容: 在下面的代码中,我想测试是否为。如果是的话,我想作为。你怎么做到这一点?如果不使用强制转换,则使用其他技术。 那里的最后一行不会编译。错误是: 协议“ SpecialController”仅具有通用要求或关联类型要求,因此只能用作通用约束。 问题答案: 不幸的是,Swift当前不支持将具有关联类型的协议用作实际类型。但是,从技术上讲这对于编译器是可行的。并且很可能在该语言的未来版本中实
问题内容: “让f = e为[测试],让g = e为![测试]”总是会出错。我有一个必须发送[Test]到的功能。将A转换为Test易于使用。但是当涉及到数组时,我必须遍历所有数据。有什么好的方法可以将[A]转换为[Test]。 问题答案: 不同代码的答案是正确的,但它也是重要的是要明白,为什么你不能只是重新解释数据,而不 东西 做一个O(n)的转换行走,虽然在一个盒子包装的每个元素。 是一个数组
问题内容: 我正在尝试通过符合协议的编码模型来获取数据。但是它无法像下面的代码那样调用func : 但是在另一个演示中,效果很好,为什么呢? 问题答案: 解决方案1。 https://github.com/satishVekariya/SVCodable 试试这个代码,它扩展了可编码 解决方案2。 避免污染带有扩展名的Apple提供的协议 用
问题内容: 我想让一个函数在Swift中接受任何数字(Int,Float,Double,…) 不使用NSNumber 问题答案: 更新: 以下答案原则上仍然适用,但是Swift 4完成了数字协议的重新设计,因此通常不需要添加自己的数字协议。在构建自己的系统之前,请查看标准库的数字协议。 在Swift中,这实际上是不可能的。为此,您需要创建一个新协议,并使用您将在泛型函数中使用的任何方法和运算符进行
问题内容: 考虑以下代码: 我们感到恐惧,而且显然令人费解: 协议“集合”具有自定义或相关类型要求,因此只能用作通用约束。 但是,这很容易编译: 为什么?! 特别是,编译器 不 知道如何关联的类型(类型)的已经实现; 它只能得到它们已经存在的 承诺 (因为任何类型的对象 都 必须实现它们)。第一个示例中也有同样的保证!那么,为什么编译器抱怨一个而不是另一个呢? 我的问题是:在代码行中,编译器如何知