Я бы порекомендовал создать протокол, моделирующий группировку ваших типов, и расширить эти типы, чтобы они соответствовали этому протоколу.
Например, предположим, что целью этих целых чисел или строк было заполнение ячейки в стол. Вы бы сделали что-то вроде этого:
/// some example type that models a table cell
class Cell {
var value: String
init(value: String) { self.value = value }
}
protocol CellRepresentable {
func populate(in: Cell)
}
extension Int: CellRepresentable {
func populate(in cell: Cell) {
// Don't ever format numbers for user-consumption like this
// Use a NumberFormatter. This is for demo use only
cell.value = String(self)
}
}
extension String: CellRepresentable {
func populate(in cell: Cell) {
cell.value = self
}
}
let myDict: [String: CellRepresentable] = [
"key1": 1,
"key2": "value 2",
"key3": 3,
]
Ключ в том, чтобы спроектировать протокол так, чтобы он представлял абстракцию (в данном случае что-то, что может быть представлено ячейкой), а не слишком близко моделировать к конкреция (например, деталь хранилища представимого объекта - Int
или String
).
Преимущество этого подхода в том, что он действительно прост и расширяем. Вы просите эти ценности делать то, что вы от них хотите. Если бы вместо этого вы использовали перечисление, вы не смогли бы этого сделать, вам пришлось бы постоянно писать switch
случаев, и вам пришлось бы определять правильное поведение каждого case
в каждом сценарии.
Использование подобного полиморфизма означает, что вы можете легко добавить поддержку Bool
без необходимости редактировать каждый оператор switch
в вашей программе. Полиморфизм просто «заботится об этом».