[英]Swift: Array of equatable generic type
我是在最后幾天與Swift上有關泛型的一些問題作斗爭,但我找不到找到解決方法的方法:
class Store<S: State>
,其中State
是擴展Equatable protocol State: Equatable
的簡單協議。 Logger
類,我想在其中存儲一組Stores
來跟蹤它們的每個更改,並將它們的State
與它們的舊值進行比較,從而能夠檢查每次迭代中的更改。 為此,我需要在logger類中存儲任何類型的存儲數組。 當我嘗試使用val storeArray = [Store<Any>]
,問題就來了,這是行不通的,因為Any不是Equatable
類型,我將需要它們擴展Equatable
或NSObject
以便能夠在兩個之間比較狀態他們。
可以在Swift中實現嗎? 還是找到另一種比較兩個項目而不使泛型擴展Equatable
協議的方法?
如果您想檢查實現:
狀態:
protocol State: Equatable {
}
店鋪:
class Store<S: State> {
private var _initialState: S
private var _state: S
private var processor = PublishSubject<S>()
init(initialState: S) {
_initialState = initialState
_state = initialState
}
var state: S {
get {
return _state
}
set(value) {
if (value != state) {
_state = value
processor.onNext(value)
}
}
}
func initialState() -> S {
return _initialState
}
/// Initialize the store. Called after all stores instances are ready.
func initialize() {
//TODO Check if its possible to force an override over a method
preconditionFailure("This method must be overridden")
}
}
根據Vadian的建議,我嘗試將其移至關聯類型的協議中:
protocol Store: class {
associatedtype State : StateDelegate
var processor : PublishSubject<State> { get }
var _state : State { get set }
var state: State { get set }
func initialState() -> State
func flowable() -> Observable<State>
func initialize() -> Void
}
extension Store {
var state: State {
get {
return _state
}
set(value) {
if (value != state) {
_state = value
processor.onNext(value)
}
}
}
func flowable() -> Observable<State> {
return processor.startWith(state)
}
func initialState() -> State {
return State.init()
}
}
但是,當我嘗試創建[Store]
數組時,我檢索了下一個錯誤: Protocol 'Store' can only be used as a generic constraint because it has Self or associated type requirements
我想我現在明白你的問題了。 該解決方案如何:
不必讓State
符合Equatable
,而是向協議添加自己的自定義相等性檢查; 這樣,您可以將狀態存儲在數組中( var states: [State]
)。 缺點是您不能使用泛型,而必須像過去那樣在類型中檢入代碼。
例如, State
協議的簡單版本:
protocol State {
func isEqualTo(_ other: State) -> Bool
}
您的具體狀態類型必須實現isEqualTo
並在測試相等性之前執行類型檢查:
struct State1: State {
var foo: String
func isEqualTo(_ other: State) -> Bool {
guard let state1 = other as? State1 else { return false }
return self.foo == state1.foo
}
}
現在,您可以將狀態存儲在數組中,例如,檢查是否已包含新狀態:
let states: [State] = [ State1(foo: "hi"), State2(bar: 42), State1(foo: "bye")]
let newState = State2(bar: 42)
let containsNewState = states.contains { $0.isEqualTo(newState )}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.