2016-12-07 5 views
0

У меня есть класс StateMachine<A>Как использовать Swift протоколы с Generic методы и общие типы

final class StateMachine<A> { 

    private var previousState: State? = nil 
    private var currentState: State 
    private var content: A? 
    var delegate: StateMachineDelegate? 
    var state: State = .loading { 
     didSet { 
      previousState = currentState 
      currentState = state 
     } 
    } 

    init(currentState: State, delegate: StateMachineDelegate?) { 
     self.currentState = currentState 
    } 
} 

и протокол делегата StateMachineDelegate

protocol StateMachineDelegate { 
    func updateWith(content: A) 
} 

Я пытаюсь выразить, что если создается StateMachine с типом A, делегат должен реализовать метод func updateWith(content: A), который принимает параметр того же типа A. Возможно ли это?

+2

Вашего кода имеет много проблем в настоящее время вы не можете поместить вложенные типов в дженерик ('перечислимой State'); вы должны инициализировать все необязательные свойства в 'init'; вы должны указать 'associatedtype' в своем делетете-протоколе. – user28434

ответ

2

Вы бы осуществить то, что вы просите, добавив еще один параметр типа:

final class StateMachine<A, Delegate: StateMachineDelegate> where Delegate.A == A { 

    private var previousState: State? = nil 
    private var currentState: State 
    private var content: A? 
    var delegate: Delegate? 
    var state: State = .loading { 
     didSet { 
      previousState = currentState 
      currentState = state 
      delegate?.updateWith(content: state) 
     } 
    } 

    init(currentState: State, delegate: Delegate?) { 
     self.currentState = currentState 
    } 
} 

protocol StateMachineDelegate { 
    associatedtype A 
    func updateWith(content: A) 
} 

Но я бы не сделать это таким образом. Если ваш делегат действительно просто метод обновления, то замыкание является лучшим решением:

final class StateMachine<A> {  
    // ... 
    private var content: A? 
    var notify: (A) -> Void 

    var state: State = .loading { 
     didSet { 
      previousState = currentState 
      currentState = state 
      notify(state) 
     } 
    } 

    init(currentState: State, notify: @escaping (A) -> Void) { 
     self.currentState = currentState 
     self.notify = notify 
    } 
} 
+0

Отличный ответ! Спасибо. –