Протокол со связанным типом. Как избежать ручного назначения типа для всех реализаций протокола - PullRequest
0 голосов
/ 12 января 2019

Я делаю свою собственную простую реализацию Redux / Flux и пытаюсь смоделировать некоторые структуры данных.

В основном у меня есть протокол состояния, который может иметь действие связанного типа.

protocol State {
    associatedtype ActionType: StateAction
} 

Тогда я определяю мои состояния как:

struct BoxState: State {
    typealias ActionType = Action
    var boxes:[Box]
}

extension BoxState {
    enum Action: StateAction {
        case select(String)
        case reshape(String, CGRect)
        case delete(String)
        case add(CGPoint)
    }
}

Что мне не нравится в этом, так это то, что мне придется определять associatedtype для каждой реализации протокола, даже если каждое перечисление будет иметь одинаковый тип.

1 - Есть ли способ заставить реализацию каждого State иметь тип enum Action ?. Я понимаю, что Action на самом деле имеет тип BoxState.Action, но, возможно, есть способ абстрагировать его еще лучше.

Редактировать: Большое объяснение, не требуется для вопроса выше, но может служить объяснением: Я начал делать легкую реализацию Redux, потому что мне нравятся функции редуктора и представления, реагирующие на состояние.

Как предлагается здесь, как предлагается здесь, магазин должен отправлять действия. Это моя очень грубая реализация:

protocol StateAction {}

protocol State {
    associatedtype ActionType: StateAction
}

protocol Dispatcher {
    associatedtype Action: StateAction
    func dispatch(_ action: Action)
}

class StateStore<Type: State>: Dispatcher {

    typealias Action = Type.ActionType

    private var subscribers:[(Type)->()] = []
    var onDispatch:((Action)->())?

    var state: Type! {
        didSet {
            self.didUpdateState(state)
        }
    }

    func didUpdateState(_ state: Type) {
        self.subscribers.forEach { $0(state) }
    }

    func addSubscriber(_ subscriber: @escaping (Type)->())  {
        self.subscribers.append(subscriber)
    }

    func dispatch(_ action: Action) {
        self.onDispatch?(action)
    }
}

Что я считаю неправильным, так это то, что State определяет Action s. Представления - это те, которые запускают действия, и эти действия должны обрабатываться для изменения одного или нескольких состояний. Тем не менее, «техническая» проблема, объясненная в начале, может иметь решение.

1 Ответ

0 голосов
/ 12 января 2019

Вам нужен тип по умолчанию. Тогда тип будет одинаковым для всех реализованных структур / классов.

protocol State {
    associatedtype ActionType: StateAction = BoxState.Action
} 
...