Ответ
Типизированный массив [Element] в Swift хранит элементы одного типа. Для гетерогенных коллекций используйте следующие подходы, от наиболее к наименее предпочтительному:
1. Enum с ассоциированными значениями (типобезопасный и рекомендуемый)
enum HeterogeneousValue {
case integer(Int)
case text(String)
case floatingPoint(Double)
case boolean(Bool)
}
let collection: [HeterogeneousValue] = [
.integer(42),
.text("Hello"),
.floatingPoint(3.14),
.boolean(true)
]
for item in collection {
switch item {
case .integer(let value): print("Int: (value)")
case .text(let value): print("String: (value)")
case .floatingPoint(let value): print("Double: (value)")
case .boolean(let value): print("Bool: (value)")
}
}
2. Протоколы (когда у элементов общая функциональность)
protocol Renderable {
func render() -> String
}
struct Label: Renderable { func render() -> String { "Label" } }
struct Button: Renderable { func render() -> String { "Button" } }
let uiElements: [Renderable] = [Label(), Button()]
uiElements.forEach { print($0.render()) }
3. Тип Any (используйте с осторожностью)
let mixedArray: [Any] = [1, "Text", 3.14, true]
for element in mixedArray {
switch element {
case let intValue as Int: print("Integer: (intValue)")
case let stringValue as String: print("String: (stringValue)")
case let doubleValue as Double: print("Double: (doubleValue)")
case let boolValue as Bool: print("Bool: (boolValue)")
default: print("Unknown type")
}
}
Рекомендации:
- Предпочитайте enum для фиксированного набора типов — это обеспечивает безопасность типов и исчерпывающую обработку в
switch. - Используйте протоколы, когда важна общая поведенческая контракт.
- Избегайте
Any— он обходит систему типов Swift, требует ручных проверок и подвержен ошибкам времени выполнения.
Ответ 18+ 🔞
А, ну вот, опять про эти ваши массивы в Swift, блядь. Сидишь такой, пишешь код, а тут — бац! — и надо запихнуть в одну кучу и числа, и строки, и ещё какую-нибудь хуйню. Обычный-то массив [Element] на такое скажет: «Иди нахуй, чувак, я с одним типом работаю». Ну и правильно, блядь, он же типизированный, не распиздяйство какое.
Но выходы есть, ёпта. Вот тебе три штуки, от самого годного до такого, от чего сам Стив Джобс в гробу перевернулся бы.
1. Enum — наш царь и бог, типобезопасность ебать
Это когда ты заранее знаешь, какие типы тебе могут понадобиться. Красота, блядь, а не подход. Создаёшь enum и на каждый случай вешаешь ассоциированное значение — как рюкзачок для данных.
enum HeterogeneousValue {
case integer(Int)
case text(String)
case floatingPoint(Double)
case boolean(Bool)
}
let collection: [HeterogeneousValue] = [
.integer(42),
.text("Hello"),
.floatingPoint(3.14),
.boolean(true)
]
for item in collection {
switch item {
case .integer(let value): print("Int: (value)")
case .text(let value): print("String: (value)")
case .floatingPoint(let value): print("Double: (value)")
case .boolean(let value): print("Bool: (value)")
}
}
Вот видишь? Компилятор тебя за руку держит, не даёт наебнуться. Забыл кейс в свитче? Он тебе: «Э, бошка думай, не все случаи обработал, мудак!». Идеально.
2. Протоколы — когда всем надо делать одно и то же
Допустим, у тебя там UI элементы: лейблы, кнопки, свитчи. И всем им надо, например, отрендериться. Ну так объедини их протоколом, ёпта!
protocol Renderable {
func render() -> String
}
struct Label: Renderable { func render() -> String { "Label" } }
struct Button: Renderable { func render() -> String { "Button" } }
let uiElements: [Renderable] = [Label(), Button()]
uiElements.forEach { print($0.render()) }
Все довольны, все рендерятся. Каждый объект — свой тип, но в массиве они все Renderable. Удобно, блядь, и логично.
3. Any — тёмная сторона, в которую лучше не совать свой хуй
А вот это уже, прости господи, чистое распиздяйство. Типа «закину всё в одну кучу, а там разберёмся». Swift на такое смотрит и тихо плачет в углу.
let mixedArray: [Any] = [1, "Text", 3.14, true]
for element in mixedArray {
switch element {
case let intValue as Int: print("Integer: (intValue)")
case let stringValue as String: print("String: (stringValue)")
case let doubleValue as Double: print("Double: (doubleValue)")
case let boolValue as Bool: print("Bool: (boolValue)")
default: print("Unknown type")
}
}
Смотри, что происходит: ты теряешь всю безопасность типов нахуй. Добавил завтра какой-нибудь URL в массив — и получи default ветку, а то и креш, если неаккуратно кастовать будешь. Это как ходить по тонкому льду с Any вместо коньков — один хуй провалишься.
Короче, запомни, как «Отче наш»:
- Enum — когда типы известны и их список не меняется каждый день. Это топ, это наше всё.
- Протоколы — когда объекты разные, но делать они должны что-то общее.
Any— используй только если тебя заставили под дулом пистолета, или ты реально хочешь себе проблем на ровном месте. Доверия к такому коду — ноль ебать.
Выбирай с умом, а не как последний говнокодер.