Swift: индекс элемента в enum (CaseIterable) - PullRequest
0 голосов
/ 28 февраля 2019

Следующий код (компилируется без ошибок) возвращает индекс элемента в конкретном типе перечисления CaseIterable

public enum MyEnum : CaseIterable {
    case ONE, TWO, THREE

    public func ordinal() -> Int? {
       return MyEnum.allCases.firstIndex(of: self)
    }
}

Я хочу создать универсальную функцию для работы со всеми перечислениями CaseIterable.

Если я попытаюсь:

 public extension CaseIterable {

    public func ordinal() -> Int? {
        return CaseIterable.allCases.firstIndex(of: self)
    }
 }

Я получу ошибку компилятора "Member 'allCases' cannot be used on value of protocol type 'CaseIterable'; use a generic constraint instead", что вполне логично, поскольку фактический тип перечисления неизвестен ".

Когда я пытаюсь CaseIterable<T>, Я получаю еще одну ошибку, так как CaseIterable не объявлен как универсальный тип.

Есть ли способ?

1 Ответ

0 голосов
/ 28 февраля 2019

Требуется пара изменений:

  1. Тип возврата должен быть Self.AllCases.Index?, а не Int?.На практике эти типы будут эквивалентны, как показано ниже.
  2. Вы также должны ограничить любые типы Equatable, потому что вам нужно быть уравновешенным, чтобы использовать firstIndex(of:).Опять же, на практике любой CaseIterable обычно будет перечислением без связанных значений, то есть он будет автоматически уравниваемым.
  3. (Необязательное изменение) Эта функция никогда не вернет nil, потому что вы находите одиндело в CaseIterable.Таким образом, вы можете удалить опцию для типа возврата (Self.AllCases.Index) и принудительно развернуть.

Пример:

public extension CaseIterable where Self: Equatable {

    public func ordinal() -> Self.AllCases.Index {
        return Self.allCases.firstIndex(of: self)!
    }

}

enum Example: CaseIterable {

    case x
    case y

}

Example.y.ordinal()  // 1
type(of: Example.y.ordinal()) // Int

Лично я бы добавил, что обычно "Ordinal"означает что-то другое, чем то, что вы делаете, и я бы рекомендовал изменить имя функции на elementIndex() или что-то в этом роде.Но это в стороне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...