Можете ли вы использовать замыкания в перечислении в качестве параметров в Swift? - PullRequest
0 голосов
/ 22 сентября 2019

если у вас есть функция в Swift, которая выполняет замыкание, можете ли вы заставить параметр указывать только то, что в enum, как это делается с помощью init ()?

// function that takes a closure as a param

func calculator (n1: Int, n2: Int, operation: (Int, Int) -> Int) -> Int {
    return operation(n1, n2)
    }

// sample call.  Note: I'd like the closure to be an enum so that the programmer can only pick from items listed in the enum.

let myCalc = calculator(n1: 5, n2: 6 ) {$0 * $1}

// list of valid choices in an enum

enum CalcOptions {
    case Add {$0 + $1}
    case Subtract {$0 - $1}
    case Multiply {$0 * $1}
    case Divide {$0 / $1}
}

// Note: this gives an error (can't have the closure on the same line), I'd like the elements in CalcOptions to be closures.

// I can't do this because it's not a type listed:

var calcClosure: Closure {
    switch self {
    case .Add: return {$0 + $1}
    case .Subtract: return {$0 - $1}
    case .Multiply: return {$0 * $1}
    case .Divide: return {$0 / $1}
    }
}

Если вы хотитеограничьте использование только теми параметрами, которые перечислены в enum, как вы можете, когда вы устанавливаете init (), как бы вы это сделали?

AFAIK, когда вы используете enum в init (), он делает этоработать как тип данных, так что пользователь этого init может выбирать только из списка, который появляется.

Я хотел бы иметь такую ​​же функциональность в функции, чтобы пользователь мог выбирать только изэлементы, перечисленные в перечислении.

Пример в классе, где customerChosenType ограничен CarType в init () ... когда пользователь выбирает этот init, он получает всплывающее окно в Xcode, которое ограничивает ввод доперечисление перечисления:

enum CarType {
    case Sedan
    case Coupe
    case Hatchback
    case FastBack
}

   init(customerChosenType : CarType){
    typeOfCar01 = customerChosenType
}

1 Ответ

1 голос
/ 22 сентября 2019

Перечисления Swift не могут иметь замыкания как rawValues, поэтому вам может потребоваться связать каждый случай и соответствующее ему закрытие другими способами, например:

enum CalcOptions {
    case add
    case subtract
    case multiply
    case divide
}
extension CalcOptions {
    var operation: (Int, Int)->Int {
        switch self {
        case .add:      return {$0 + $1}
        case .subtract: return {$0 - $1}
        case .multiply: return {$0 * $1}
        case .divide:   return {$0 / $1}
        }
    }
}

func calculator (n1: Int, n2: Int, option: CalcOptions) -> Int {
    return option.operation(n1, n2)
}
print(calculator(n1: 2, n2: 3, option: .add)) //->5

Или, если вы используете Swift 5+, вы можете сделать свой enum вызываемым :

@dynamicCallable
enum CalcOptions {
    case add
    case subtract
    case multiply
    case divide

    func dynamicallyCall(withArguments args: [Int])->Int {
        let n1 = args[0], n2 = args[1]
        switch self {
        case .add:
            return n1 + n2
        case .subtract:
            return n1 - n2
        case .multiply:
            return n1 * n2
        case .divide:
            return n1 / n2
        }
    }
}

func calculator(n1: Int, n2: Int, operation: CalcOptions) -> Int {
    return operation(n1, n2)
}
print(calculator(n1: 2, n2: 3, operation: .multiply)) //->6
...