PAT обычно сложны и не требуют более простого решения. Я бы посоветовал вам придумать более простой дизайн для вашей проблемы. Проблема с вашим методом на самом деле заключается в том, что у вас есть PAT и вложенные протоколы, и вы пытаетесь заставить их работать вместе.
Даже если вы наберете erase Action
для какого-либо типа, например AnyAction
, эти два разных типа DogAction
и CatAction
снова создадут разные типы, и вы не сможете смешивать их внутри массива. Что вы можете сделать, это иметь два типа стираний, один для Action
, а другой для StateType
. Когда вы оборачиваете CatAction
или DogAction
внутри AnyAction
, они оба затем переносятся в состоянии стирания типа до AnyState
.
Вот один пример, к которому вы могли бы приблизиться, стирая оба протокола,
protocol StateType { }
struct DogState: StateType { }
struct CatState: StateType { }
protocol Action {
associatedtype ST: StateType
func process() -> ST
}
struct DogAction: Action {
func process() -> DogState { return DogState() }
}
struct CatAction: Action {
func process() -> CatState { return CatState() }
}
struct AnyState: StateType {
let state: StateType
init(_ state: StateType) {
self.state = state
}
}
struct AnyAction: Action {
typealias ST = AnyState
let processor: () -> AnyState
init<T: Action>(_ a: T) {
self.processor = {
return AnyState(a.process())
}
}
func process() -> AnyState {
return processor()
}
}
let cat = AnyAction(CatAction())
let dog = AnyAction(DogAction())
let actions = [cat, dog]
actions.forEach { action in
action.process()
}
Я все еще думаю, что вам следует переосмыслить свое решение, это может усложниться по мере увеличения количества типов.