Ras*_*sto 5 generics compiler-errors interface ios swift
请参阅下面的自包含示例.编译器在最后一行(标记为COMPILE ERROR
)上报告错误,其中我将SimpleTrain
协议类型的实例分配给它(根据我的最佳判断)符合.我怎样才能编译?我究竟做错了什么?或者这个编译器问题?
protocol Train {
typealias CarriageType
func addCarriage(carriage: CarriageType)
func shortTrain<ShortType: Train where ShortType.CarriageType == CarriageType>() -> ShortType
}
class SimpleTrain<T> : Train {
typealias CarriageType = T
private var carriages: [T] = [T]()
func addCarriage(carriage: T) {
carriages.append(carriage)
}
func shortTrain<ShortType: Train where ShortType.CarriageType == CarriageType>() -> ShortType {
let short = SimpleTrain<T>()
short.addCarriage(carriages[0])
return short //COMPILE ERROR: SimpleTrain<T> is not convertible to 'ShortType'
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:即使我明确地向下转换shortTrain
上面的返回类型(以便上面的代码片段的最后一行读取return short as ShortType
),如安东尼奥所建议的那样,在调用函数时仍然存在编译错误shortTrain
:
let s = SimpleTrain<String>()
s.addCarriage("Carriage 1")
s.addCarriage("Carriage 2")
let a = s.shortTrain() //ERROR: Cannot convert the expression's type '()' to type 'Train'
let b = s.shortTrain<SimpleTrain<String>>() //ERROR: cannot explicitly specialize a generic function
Run Code Online (Sandbox Code Playgroud)
首先,您要阅读规范线程devforums 上关于此问题的您特别想跳过来阅读 jckarter 的评论。
现在来回答编辑后的问题:
let a = s.shortTrain() //ERROR: Cannot convert the expression's type '()' to type 'Train'
Run Code Online (Sandbox Code Playgroud)
这是因为您没有为编译器提供足够的信息来确定a
. 仔细思考它所看到的:
func shortTrain<ShortType: Train where ShortType.CarriageType == CarriageType>() -> ShortType {
let a = s.shortTrain()
Run Code Online (Sandbox Code Playgroud)
编译器需要在编译时找出类型a
,它无法处理抽象类型。它需要一个完全指定的类型ShortType
(一切都确定下来;指定所有泛型,解析所有类型别名)。它环顾四周,看到了一些对 的约束ShortType
,但它没有看到任何实际给出类型的东西。它所拥有的只是a
,这并没有给它任何提示。
不幸的是,这使得你必须明确地告诉它你想要发生什么。
let a: SimpleTrain<String> = s.shortTrain()
Run Code Online (Sandbox Code Playgroud)
这可能与您想要的相反,但这就是您现在可以在 Swift 中做的所有事情。Swift 团队(多次)表示,他们很清楚相关类型的这些问题(以及类型系统中的其他几个相关弱点)。他们特别意识到 Scala 类型系统可以处理这些事情,并且与当前的 Swift 类型系统有很多共同点(尽管根据我的经验,让复杂的路径依赖关联类型在 Scala 中工作也可能会导致头发撕裂) )。
也就是说,从您的示例中并不完全清楚您计划使用此功能做什么。有些火车会返回不同的类型作为它们的shortTrain()吗?
我发现这些问题在一般情况下经常会爆发,但在您面前的应用程序的特定情况下往往是可以解决的。在 Swift 中用代码构建真正任意的类型来解决所有问题是很困难的,但当你专注于你真正需要的类型时,它通常会奏效。例如,如果shortTrain()
返回Self
,这显然会变得更简单。如果调用者知道所需的结果类型,那么 aninit(shorten:)
可能可以处理它。像这样的协议方法shortCarriages() -> [CarriageType]
可以提供一个很好的桥梁。在设计上保持灵活性,其中之一几乎肯定会奏效。
归档时间: |
|
查看次数: |
2527 次 |
最近记录: |