Swift: Свяжите регистр перечисления с типом. Заводской вариант использования

#ios #swift #generics

Вопрос:

Я пытаюсь создать простую фабрику объектов, используя перечисление. Регистр перечисления определяет тип объекта, который необходимо создать фабрике.

Я хотел бы иметь один метод, который получает перечисление и возвращает экземпляр. Задача здесь состоит в том, чтобы найти способ «привязать» регистр перечисления к типу объекта, который он должен создать.

Альтернативой является создание одного метода для каждого создаваемого класса, например: getMessenger() . В этом случае мне вообще не понадобились бы перечисления. Но я хочу попробовать перечислить. Спасибо!

То, что я пробовал до сих пор:

 class ModuleFactory {
    
    enum Module {
        case messenger
    }
    
    static func get<T>(module: Module) -> T {
        switch module {
        case .messenger: return Messenger(api: API(), configuration: Messenger.Configuration(enabledMenuOptions: [])) as! T
        }
    }
}
 

Комментарии:

1. Я не думаю, что здесь уместно использовать перечисления. Допустим , у меня есть еще один случай перечисления anotherModule , и у меня есть let e = Bool.random() ? Module.messenger : .anotherModule . Какой тип get вернется, если я это сделаю get(module: e) ? Компилятор не может сказать!

2. Я бы просто сделал альтернативу, которую вы описали, — имел бы один метод для получения каждого типа вещей, если у вас нет действительно веской причины для этого, о которой я не знаю.

3. Спасибо @Sweeper. Я думаю, что вы правы, избегание перечисления позволит обеспечить большую гибкость, поскольку не будет однозначной связи между перечислением и производственными данными. В любом случае было бы неплохо знать, возможно ли иметь своего рода «связанный тип» для перечисления, зависящий от случая.

4. Нет; вы не можете связать связанные типы со значениями таким образом (поскольку случаи перечисления являются значениями, а не самими типами). Есть места, где это было бы полезно; однако этот пример на самом деле не относится к их числу. То, что вы создали здесь, может быть гораздо лучше реализовано как shared статический экземпляр или параметры по умолчанию. Фабрики очень редко бывают полезны в Swift. То, что вы ищете, вероятно, связано с функцией под названием «зависимые типы», где тип может зависеть от значения, но у Swift нет этой функции (и я ожидаю, что вы ее не получите; это довольно сложная функция).