问题描述
我试图用通用协议描述一个委托属性,而不使该类通用:
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
类型称为“类型擦除器”。