Массив типов enum, соответствующих протоколу со связанным типом - PullRequest
0 голосов
/ 07 февраля 2020

Давайте рассмотрим упрощенный случай с двумя типами перечислений, соответствующими CaseIterable.

enum A: String, CaseIterable {
    case a1, a2, a3
}

enum B: String, CaseIterable {
    case b1, b2, b3
}

Я хочу создать таблицу типа ha sh, связывающую ключ (в моем примере строку) и тип *1006* перечислений:

let dict: [String : CaseIterable.Type] = [ // Error here: Protocol 'CaseIterable' can only be used as a generic constraint because it has Self or associated type requirements
    "my key A" : A.self,
    "my key B" : B.self
]

В конечном итоге мне нужно «запросить» у моей таблицы ha sh конкретный ключ c и применить к результату метод протокола (скажем, allCases).

let cases = dict["my key A"]!.allCases

Есть предложения?

1 Ответ

1 голос
/ 08 февраля 2020

Я хочу отобразить меню со списком всех возможных вариантов.

То есть вам нужны строки, а не сами случаи. Это абсолютно выполнимо. Во-первых, начните с того, что вы действительно хотите, чтобы тип делал в форме протокола:

protocol CaseNamed {
    static var caseNames: [String]
}

Если бы у вас было это, вы могли бы построить то, что вы хотите:

var enums: [CaseNamed.Type] = [A.self, B.self]
enums.flatMap { $0.caseNames }

(я называю это "wi sh управляемой разработкой." У меня будет sh У меня был тип, который мог бы ....)

Теперь вам просто нужно согласовать типы с CaseNamed осуществляя caseNames. К счастью, это легко, если тип также соответствует CaseIterable:

extension CaseNamed where Self: CaseIterable {
    static var caseNames: [String] {
        self.allCases.map { "\($0)" }
    }
}

Но у вас могут быть типы CaseNamed, которые не соответствуют CaseIterable. CaseIterable не является обязательным требованием. Просто приятно, если он у тебя есть. Вот полный код:

protocol CaseNamed {
    static var caseNames: [String] { get }
}

enum A: String, CaseIterable, CaseNamed {
    case a1, a2, a3
}

enum B: String, CaseIterable, CaseNamed {
    case b1, b2, b3
}

extension CaseNamed where Self: CaseIterable {
    static var caseNames: [String] {
        self.allCases.map { "\($0)" }
    }
}

var enums: [CaseNamed.Type] = [A.self, B.self]

enums.flatMap { $0.caseNames }

Теперь, конечно, вы можете также захотеть, чтобы этот протокол CaseNamed выполнял другие функции, поэтому вы можете добавлять эти другие вещи. Но вам нужно думать с точки зрения вызывающего кода и того, что ему необходимо для выполнения своей работы.

...