我可以使用泛型协议来描述非泛型类型的委托吗?

Can I use a generic protocol to describe a delegate in a non generic type?

我正在尝试使用通用协议描述委托 属性,而不使 class 通用:

protocol ActionHandler: class {
  associatedtype Action
  func handle(_ action: Action)
}

enum SomeAction {
  case dismiss
}

class Foo {
  typealias Action = SomeAction
  //  Protocol 'ActionHandler' can only be used as a generic constraint because it has Self or associated type requirements
  weak var handler: ActionHandler?
  // Ideally some form of ActionHandler<Action>?
}

class Handler: ActionHandler {
  func handle(_ action: SomeAction) {
    switch action {
      case .dismiss:
        print("dismiss")
    }
  }
}

let handler = Handler()
Foo().handler = handler

我可以用闭包代替 属性,但我不太喜欢这种模式,对于协议中描述的每个方法我都必须这样做。

enum SomeAction {
  case dismiss
}

class Foo {
  typealias Action = SomeAction
  var handleAction: ((Action) -> Void)?
}

class Handler {
  func handle(_ action: SomeAction) {
    switch action {
      case .dismiss:
        print("dismiss")
    }
  }
}

let handler = Handler()
Foo().handleAction = handler.handle(_:)

有更好的解决方案吗?

没有 使 Foo 通用,但您需要一个很好的理由不这样做。无论如何,这是一种建立在闭包方法之上的方法——如果我们将这些闭包包装在一个类型中会怎样?

class AnyActionHandler<Action> : ActionHandler {
    var handleClosure: (Action) -> Void
    func handle(_ action: Action) {
        handleClosure(action)
    }
    
    init<ActionHandlerType: ActionHandler>(_ actionHandler: ActionHandlerType) where ActionHandlerType.Action == Action {
        handleClosure = actionHandler.handle(_:)
    }
}

现在如果 ActionHandler 中有更多的方法,你可以只添加到这个类型中,而不是在你分配给 Foo.handler 的地方添加它们。 Foo可以刚好有

weak var handler: AnyActionHandler<Action>?

分配处理程序如下所示:

Foo().handler = AnyActionHandler(handler)

这种AnyActionHandler类型称为“类型橡皮擦”。