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

问题描述

我试图用通用协议描述一个委托属性,而不使该类通用:

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类型称为“类型擦除器”。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...