Проверьте, можно ли создать перечисление из параметра в переключателе - PullRequest
0 голосов
/ 18 января 2019

У меня есть перечисление что-то вроде ...

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 и ввести регистр только в том случае, если он может быть создан, чтобы я мог просто использовать тот, который был создан, и не создавать второго один

Ответы [ 2 ]

0 голосов
/ 19 января 2019

Другой альтернативой является 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.

также может увеличиться.
0 голосов
/ 18 января 2019

Не делайте это слишком сложным. Включите значение 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?), а затем все еще проверит остальные регистры.

...