我有一个类似...的枚举
enum MyEnum {
case a(Foo)
case b
case c(Bar)
enum Foo: String {
case one
case two
}
enum Bar: String {
case three
case four
}
}
我正在尝试为此创建一个可失败的初始化函数,以便您可以像这样调用它...
MyEnum(base: "a", parameter: "one")
或
MyEnum(base: "b", parameter: nil)
我已经像这样工作了(但是笨拙)...
init?(base: String, parameter: String?) {
switch (base, parameter) {
case ("a", let p?) where Foo(rawValue: p) != nil:
self = .a(Foo(rawValue: p)!)
case ("b", _):
self = .b
case ("c", let p?) where Bar(rawValue: p) != nil:
self = .c(Bar(rawValue: p)!)
default:
return nil
}
}
这将打开base
,然后在输入大小写之前检查是否可以创建下一个值。
但是,我现在必须创建两次Foo
或Bar
,然后强制打开第二个包装。
有没有一种方法来创建开关盒以创建Foo
或Bar
,并且仅在可以创建开关盒的情况下才输入该盒,这样我就可以使用创建的开关盒而不必创建第二个?
答案 0 :(得分:5)
不要太复杂。开启base
值,并在需要时使用parameter
或if
以及可选的绑定来处理guard
:
init?(base: String, parameter: String?) {
switch base {
case "a":
guard let p = parameter, let foo = Foo(rawValue: p) else { return nil }
self = .a(foo)
case "b":
self = .b
case "c":
guard let p = parameter, let bar = Bar(rawValue: p) else { return nil }
self = .c(bar)
default:
return nil
}
}
易于理解,没有强制展开,并且Foo
或Bar
值仅创建一次(如果需要)。
这也最小化了测试:例如,MyEnum(base: "a", parameter: nil)
将转到"a"
情况并返回nil
。在您的switch语句中,它将不符合("a", let p?)
的情况,然后仍然检查其余的情况。
答案 1 :(得分:0)
另一种替代方法是在switch
和Foo
初始化程序上同时使用Bar
:
init?(base: String, parameter: String?) {
switch (base, parameter.flatMap { Foo.init(rawValue: $0) ?? Bar(rawValue: $0) } as Any?) {
case ("a", let foo as Foo):
self = .a(foo)
case ("b", _):
self = .b
case ("c", let bar as Bar):
self = .c(bar)
default:
return nil
}
}
不利之处在于,如果Foo
和Bar
具有共同的情况,那么您可能无法获得想要的结果。同样,如果案件数量增加,switch
上的表达式也可能增加。