protocol Item {
// Any useful functionality common between the two.
}
extension String: Item {}
extension Array: Item where Element: Item {}
let strarr2: [Item] = ["Hello", "bye", "str1", ["str2", "str3"]]
It’s more succinct, but it can’t be checked for exhaustively. Additional conformances can also be added behind your back if the protocol is public. So which strategy is actually better depends on the target use case.
Ah cool, thanks, as you point out, things could change for public protocols, but this is nice in that I don't have to wrap everything. Would be nice to be able to do something like my first example some day.
I think you can combine enums and protocol to have the best of the two worlds:
indirect enum Item {
case value(String)
case container([Item])
}
protocol ItemRepresentable {
var asItem: Item { get }
}
extension String: ItemRepresentable {
var asItem: Item { .value(self) }
}
extension Array<Item>: ItemRepresentable {
var asItem: Item { .container(self) }
}
let items: [ItemRepresentable] = ["Hello", "bye", "str1", ["str2", "str3"]]
for x in items {
switch x.asItem {
case let .value(v):
print(“value: \(v)”)
case let .container(c):
print(“container: \(c)”)
}
}