考虑以下代码。它允许您通过传入可以处理有效负载的闭包来实例化处理器。闭包可以是六种签名类型之一。以下是我实施的方法:
我想知道是否有更简单/更好的方式来写这个。我想也许通过使用带有关联值的枚举,但这意味着我必须将闭包包装在枚举中,然后将枚举传递给初始化器。我希望尽可能避免这种情况。
struct Payload {
let stringVal : String
let intVal : Int
}
class Processor{
init(action:Any){
switch action {
case let action as () -> Void,
let action as () -> Error?,
let action as (String) -> Void,
let action as (String) -> Error?,
let action as (Int) -> Void,
case let action as (Int) -> Error?,
default: fatalError("Action does not have a supported signature")
}
self.action = action
}
let action:Any
func performAction(payload:Payload) -> Error? {
switch action {
case let action as () -> Void:
action()
case let action as () -> Error?:
return action()
case let action as (String) -> Void:
action(payload.stringVal)
case let action as (String) -> Error?:
return action(payload.stringVal)
case let action as (Int) -> Void:
action(payload.intVal)
case let action as (Int) -> Error?:
return action(payload.intVal)
default: fatalError("Action does not have a supported signature")
}
return nil
}
}
此外,在初始化程序中,我正在执行模式匹配以确定我是否有有效匹配,我收到编译器警告说我已设置,但从未使用过action
。但是,如果我用_
替换它,那么我会得到一个警告,我没有绑定到模式中的任何内容。如何在对我不关心值的模式执行测试的同时抑制警告?
答案 0 :(得分:0)
避免使用Any
类型的参数。使用带有相关类型的枚举:
enum Action {
case a1(() -> Void)
case a2(() -> Error?)
case a3((String) -> Void)
case a4((String) -> Error?)
case a5((Int) -> Void)
case a6((Int) -> Error?)
}
struct Payload {
let stringVal : String
let intVal : Int
}
class Processor{
let action: Action
init(action: Action) {
self.action = action
}
func performAction(payload: Payload) -> Error? {
var error: Error? = nil
switch action {
case let .a1(closure):
closure()
case let .a2(closure):
error = closure()
case let .a3(closure):
closure(payload.stringVal)
case let .a4(closure):
error = closure(payload.stringVal)
case let .a5(closure):
closure(payload.intVal)
case let .a6(closure):
error = closure(payload.intVal)
}
return error
}
}
这可确保您只能将有效操作传递到Payload类。
Action案例值需要有更好的命名约定,但这会让你开始。
以下是用法示例:
let payload = Payload(stringVal: "Hello", intVal: 42)
let myAction = {
print("Working")
}
let action = Action.a1(myAction)
let processor = Processor(action: action)
let error = processor.performAction(payload: payload)
另一种方法是将Action
置于Processor
内部,并为Processor
提供6个初始值设定项。
struct Payload {
let stringVal : String
let intVal : Int
}
class Processor{
enum Action {
case a1(() -> Void)
case a2(() -> Error?)
case a3((String) -> Void)
case a4((String) -> Error?)
case a5((Int) -> Void)
case a6((Int) -> Error?)
}
private let action: Action
init(_ closure: @escaping () -> Void) {
self.action = .a1(closure)
}
init(_ closure: @escaping () -> Error?) {
self.action = .a2(closure)
}
init(_ closure: @escaping (String) -> Void) {
self.action = .a3(closure)
}
init(_ closure: @escaping (String) -> Error?) {
self.action = .a4(closure)
}
init(_ closure: @escaping (Int) -> Void) {
self.action = .a5(closure)
}
init(_ closure: @escaping (Int) -> Error?) {
self.action = .a6(closure)
}
func performAction(payload: Payload) -> Error? {
var error: Error? = nil
switch action {
case let .a1(closure):
closure()
case let .a2(closure):
error = closure()
case let .a3(closure):
closure(payload.stringVal)
case let .a4(closure):
error = closure(payload.stringVal)
case let .a5(closure):
closure(payload.intVal)
case let .a6(closure):
error = closure(payload.intVal)
}
return error
}
}
let payload = Payload(stringVal: "Hello", intVal: 42)
let myAction = {
print("Working")
}
let processor = Processor(myAction)
let error = processor.performAction(payload: payload)