我疯了还是不应该这个快速的代码编译?
protocol Protocol {
typealias Thing
}
class Class<X>: Protocol {
typealias Thing = X
}
func test<X:Protocol where X.Thing == Int> () -> X {
return Class<Int>() // error: cannot convert return expression of type 'Class<Int>' to return type 'X'
}
Run Code Online (Sandbox Code Playgroud)
即使泛型类型和aliastype匹配,我似乎无法将对象强制转换为其协议.
编辑:
我通过从现有代码中提取逻辑来提出上述代码,以简化问题.这样做我犯了一些错误.这是一个更新的(并且希望不那么令人困惑)代码示例:
protocol Protocol {
typealias Thing
}
class Class<X>: Protocol {
typealias Thing = X
}
func test<Y: Protocol where Y.Thing == Int> () -> Y {
return Class<Y.Thing>()
}
Run Code Online (Sandbox Code Playgroud)
我希望编译器允许test()以结果类型编译Protocol<Int>.
在今天的Swift中你的回归类型是不可能的.具有关联类型(PAT)的协议是抽象的.应用where子句不会改变它.考虑以下代码:
let x: <WHAT-GOES-HERE?> = test()
Run Code Online (Sandbox Code Playgroud)
这是什么类型的x?没有什么可以写在那里编译.会有什么x.Type回报?你想要它是什么Protocol where Protocol.Thing == Int,但这不是Swift中的一种类型.这是一种类型约束.这是今天可以使用PAT的唯一方法.这就是为什么你不能拥有类型的属性CollectionType<Int>,以及为什么你不能编写你的test()函数.
该解决方案是一种类型橡皮擦,可将您的协议转换为具体的结构.例如:
protocol Protocol {
typealias Thing
func dosomething() -> Thing?
}
class Class<X>: Protocol {
typealias Thing = X
func dosomething() -> Thing? {
return nil
}
}
struct AnyProtocol<Thing> {
var _dosomething: () -> Thing?
func dosomething() -> Thing? {
return _dosomething()
}
}
func test() -> AnyProtocol<Int> {
return AnyProtocol(_dosomething: Class<Int>().dosomething)
}
Run Code Online (Sandbox Code Playgroud)
Swift的某些未来版本可能会为您自动生成这些类型的橡皮擦,但我不知道任何具体的Swift-evolution建议,所以我们今天必须手工编写它们.
有关构建和使用类型擦除器的更多信息,请参阅对AnySequence的一点尊重.
| 归档时间: |
|
| 查看次数: |
1801 次 |
| 最近记录: |