Необязательный параметр в случае перечисления в swift

В быстрой функции функция может иметь необязательные параметры, которые имеют значения по умолчанию, такие как:

func f(a:Int, b:Int?=nil) {}

f(1);
f(1,2);

Я хотел бы сделать это со связанными значениями с перечислением. После этого сообщения о введите безопасные URL-маршруты, я бы хотел иметь маршрут, который может принимать необязательный параметр, например:

enum StopPoint {
    case Search(query:String, limit:Int?=nil)
}

Однако он говорит, что у меня не может быть значения по умолчанию для параметра в кортеже. Однако возможно иметь такой случай, как case Arrivals(stopId:Int), но в общем случае невозможно иметь кортеж с одним именованным параметром.

Итак, возможно ли иметь перечисление с параметром по умолчанию и является ли связанное значение кортежем или нет?

Ответ 1

Что вы можете сделать:

enum StopPoint {
    case Search(query: String, limit: Int?)

    init(query: String, limit: Int? = nil) {
        self = .Search(query: query, limit: limit)
    }
}

let foo = StopPoint(query: "default")             // Search("default", nil)
let bar = StopPoint(query: "special", limit:  42) // Search("special", Optional(42))

Ответ 2

Я не думаю, что это возможно. Это просто отличная особенность function s. Ничего, что поддерживает настоящий кортеж под ним. Документы для значений параметров по умолчанию:

Вы можете определить значение по умолчанию для любого параметра в функции, назначив значение параметру после этого типа параметров. Если определено значение по умолчанию, вы можете опустить этот параметр при вызове функции.

Перечисления просто не имеют такой возможности. Вы должны явно использовать другой элемент enum для включения необязательных дополнительных параметров:

enum StopPoint {
    case Search(String)
    case SearchLimit(String, Int)
}

Перечисления довольно мощные, но не очень мощные. Вы не можете использовать значения по умолчанию, вы можете, например, не использовать тип переменной (может быть, даже больше "ограничений"):

enum StopPoint {
    case SearchMult(String...) // causes compile error
}

Что касается потенциально интересного "почему" -question: не знаю, я не настолько глубоко вовлечен в языковую архитектуру.

Ответ 3

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

enum StopPoint {
    case Search(query:String, limit:Int?)

    static func createSearch(query:String, limit:Int?=nil) -> StopPoint {
        return .Search(query: query, limit: limit)
    }
}

let myStopPoint = StopPoint.createSearch("my query")

Ответ 4

Вы можете сделать это, создав статические функции для перечисления, которые соответствуют регистру перечисления, для которого вы хотите разрешить дополнительные параметры.

enum StopPoint {
    case search(query: String, limit: Int?)

    static func search(query: String) -> StopPoint {
        return .search(query: query, limit: nil)
    }
}

Это делает так, что вы можете предоставить ограничение или нет, используя ожидаемый синтаксис:

let a = StopPoint.search(query: "Foobar")
let b = StopPoint.search(query: "Foobar", limit: 5)
let c = StopPoint.search(query: "Foobar", limit: nil)

func foo(_ stop: StopPoint) { /* ... */ }

foo(.search(query: "Foobar"))
foo(.search(query: "Foobar", limit: 5))
foo(.search(query: "Foobar", limit: nil))

Протестировано и подтверждено работа со Swift 4.2