[英]Swift Type Erasure with Generic Enum and Generic Protocol
我不得不在Swift中使用几次类型擦除,但是它总是涉及通用协议。 在这种情况下,它包含了一个通用的枚举和和通用的协议和我难倒。
这是我的通用枚举和通用协议,带有必要的扩展名:
enum UIState<T> {
case Loading
case Success([T])
case Failure(ErrorType)
}
protocol ModelsDelegate: class {
associatedtype Model
var state: UIState<[Model]> { get set }
}
extension ModelsDelegate {
func getNewState(state: UIState<[Model]>) -> UIState<[Model]> {
return state
}
func setNewState(models: UIState<[Model]>) {
state = models
}
}
这是我的类型擦除通用类:
class AnyModelsDelegate<T>: ModelsDelegate {
var state: UIState<[T]> {
get { return _getNewState(UIState<[T]>) } // Error #1
set { _setNewState(newValue) }
}
private let _getNewState: ((UIState<[T]>) -> UIState<[T]>)
private let _setNewState: (UIState<[T]> -> Void)
required init<U: ModelsDelegate where U.Model == T>(_ models: U) {
_getNewState = models.getNewState
_setNewState = models.setNewState
}
}
我遇到以下错误(它们在代码示例中被标记):
错误1:
Cannot convert value of type '(UIState<[T]>).Type' (aka 'UIState<Array<T>>.Type') to expected argument type 'UIState<[_]>' (aka 'UIState<Array<_>>')
我已经为此工作了一段时间,并且“几乎可以正常工作”的此代码有很多变体。 该错误始终与吸气剂有关。
正如@dan所指出的 ,导致此错误的问题是,在此行上,您尝试传递类型作为参数,而不是该类型的实例:
get { return _getNewState(UIState<[T]>) }
但是,我首先会质疑您对该函数使用参数,因此,获取函数肯定根本没有参数吗? 在这种情况下,您只希望_getNewState
函数具有签名() -> UIState<[T]>
,并按如下方式调用它:
get { return _getNewState() }
另外,如果协议扩展中的getNewState
和setNewState(_:)
函数仅存在以便将state
属性的获取和设置转发给类型擦除,则可以通过完全删除它们并使用闭包来简化代码类型擦除的init
中的表达式:
_getNewState = { models.state }
_setNewState = { models.state = $0 }
(这些工作通过捕获对models
参数的引用来获得,有关更多信息,请参见Closures:捕获值 )。
最后,我怀疑您的意思是在整个代码中都引用UIState<T>
而不是UIState<[T]>
,因为在这种情况下, T
引用.Success
大小写具有关联值的数组中的元素(除非您想在此处使用2D数组)。
总而言之,通过上述建议的更改,您将希望代码看起来像这样:
enum UIState<T> {
case Loading
case Success([T])
case Failure(ErrorType)
}
protocol ModelsDelegate: class {
associatedtype Model
var state: UIState<Model> { get set }
}
class AnyModelsDelegate<T>: ModelsDelegate {
var state: UIState<T> {
get { return _getNewState() }
set { _setNewState(newValue) }
}
private let _getNewState: () -> UIState<T>
private let _setNewState: (UIState<T>) -> Void
required init<U: ModelsDelegate where U.Model == T>(_ models: U) {
_getNewState = { models.state }
_setNewState = { models.state = $0 }
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.