0

I have a class StateMachine<A>

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
    }
}

and a delegate protocol StateMachineDelegate

protocol StateMachineDelegate {
    func updateWith(content: A)
}  

I'm trying to express that if the StateMachine is created with type A, the delegate should implement the method func updateWith(content: A) which accepts a parameter of the same type A. Is this possible?

1
  • 2
    Your code has a lot of problems now: you can't put nested types in generics (enum State); you must initialize all non-optional properties in your init; you must specify associatedtype in your delegate protocol. Commented Dec 7, 2016 at 14:42

1 Answer 1

2

You'd implement what you're asking for by adding another type parameter:

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)
}

But I wouldn't do it this way. If your delegate really is just an update method, then a closure is a better solution:

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
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Excellant answer! Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.