尝试使用以下代码在Swift中构建概念验证库:
import Foundation
protocol Resolver {
typealias ResolvedType
func get() -> ResolvedType
}
class FunctionResolver<T>: Resolver {
typealias ResolvedType = T
private var _resolver: () -> ResolvedType
init(resolver: () -> ResolvedType) {
_resolver = resolver
}
func get() -> ResolvedType {
return _resolver()
}
}
func singleton<T, U: Resolver where U.ResolvedType == T>(instance: T) -> U {
return FunctionResolver({ () -> T in instance }) as U
}
class TestObject {
init() { }
}
let obj = TestObject()
let r = singleton(obj)
然而,最后一行失败了:
playground466.swift:30:9: error: cannot convert the expression's type 'TestObject' to type 'Resolver'
let r = singleton(obj)
^~~~~~~~~
为什么Swift会尝试将obj
转换为Resolver
?我不太清楚我在那里失踪了什么。我认为这应该有效,因为所有类型信息都在singleton
方法中可用。
我是否在推理系统中引入了某种循环?如何修复此问题,以便最后一行按预期工作(解析为obj
的同一实例的解析器)?
我正在访问开发门户网站上的最新Xcode。
编辑:我尝试过简化它,但仍无效:
func singleton<T: Resolver>(instance: T.ResolvedType) -> T {
return FunctionResolver(resolver: { () -> T.ResolvedType in instance }) as T
}
答案 0 :(得分:2)
问题在于此功能:
func singleton<T, U>(instance: T) -> U {
return FunctionResolver({ () -> T in instance }) as U
}
无法将 U
推断为输入参数 - 而是指定用于推断类型的返回值的变量类型。如果你写:
let r = singleton(obj)
您没有提供足够的信息来确定U
是什么。所以你应该明确指定它的类型:
let r: FunctionResolver<TestObject> = singleton(obj)
我知道......错误信息没有多大帮助:)作为一般规则,如果没有意义,问题就出在其他地方。
答案 1 :(得分:1)
您似乎正在推动类型推理系统超越它的限制。
singleton()
函数使用泛型类型进行参数化,并返回该泛型类型的值。从来没有任何关于T实际上是什么类型的信息。
最简单的修复,因为Swift不支持在函数中明确提供泛型值,是确定返回类型。
let obj = TestObject()
let r : FunctionResolver = singleton(obj)
正常工作。
但是,如果您不想指定确切的类型,只需要r is Resolver
?
运气好。斯威夫特并不支持这一点。具有关联类型的协议只能用作通用约束,因为编译器错误状态。