是否可以创建不同枚举类型的数组?
例如:
MyEnums.swift:
class MyEnums {
enum FirstEnum: String {
case Type1, Type2, Type3
}
enum SecondEnum: String {
case Type1, Type2, Type3
}
}
IteratorManager.swift:
class IteratorManager {
var enumsArray = [MyEnums]()
func iterate() {
for e in enumsArray {
print(e.rawValue)
}
}
}
我尝试了许多解决方案-扩展,协议,在类中分组(如上面的例子)在struct或enum -但没有工作
是的,但是你应该知道你是怎么做的。
枚举创建一个具体的Type。Swift是类型安全语言。FirstEnum的数组不允许包含非FirstEnum类型的项。
然而,有两种方法可以实现这一点。 1。资源协议 2。类型的谎言
我将采用这两种方法,但我永远不会推荐使用第二种选择,尽管它看起来简单而难以捉摸。
我将从第二个开始。
enum FirstEnum: String {
case Type1, Type2, Type3
}
enum SecondEnum: String {
case Type1, Type2, Type3
}
让我们创建一些具体类型的枚举。
let firstEnum1 = FirstEnum.Type1
let firstEnum2 = FirstEnum.Type2
let secondEnum1 = SecondEnum.Type3
让我们用第二个选项来包装它们:
let a:[Any] = [firstEnum1, firstEnum2, secondEnum1] //works
让我们看看如何在后面提取它:
for index in a {
if let a = index as? FirstEnum { //This is bad
print(a.rawValue)
}
if let a = index as? SecondEnum { //Aweful
print(a.rawValue)
}
}
必须将其强制转换回插入的值。我们必须使用期望,谁知道我们返回的可能是String而不是Enum。因为任意可以取任意。
让我们看看如何通过第一个选项来解决这个问题:
let b:[RawRepresentable] = [firstEnum1, secondEnum1] //Cant do so because of Associated Type
这段代码不能工作,因为它的rawrepresable是一个不完整的类型。所以我们需要定义我们自己的协议。
protocol CustomStringRepresentableEnum {
var rawValue: String { get }
}
当然,我们的枚举支持rawValue,所以我们可以追溯建模这个协议。
extension FirstEnum: CustomStringRepresentableEnum { }
extension SecondEnum: CustomStringRepresentableEnum { }
现在我们可以创建一个具体已知类型的数组。
let b:[CustomStringRepresentableEnum] = [firstEnum1, firstEnum2, secondEnum1]
这很好,因为我们不允许输入任何东西,除了符合协议的东西。这是正确的类型和约束,编译器将帮助你很多,以防止坏的事情发生,如错误的类型转换。
让我们用它来证明我们写了一些好的代码。
for index in b {
print(index.rawValue)
}
就是这样。你可以在一个数组中有不同的枚举但它们必须是齐次的。你可以用Any欺骗编译器,写出丑陋的代码,或者使用协议和泛型写出有效的和健壮的代码。选择权在你。
@kandelvijaya谢谢你的回答。
到目前为止,我已经开发了一些基于属性的enum初始化的其他态度:
MyEnums.swift:
enum MyEnums {
enum FirstEnum: String {
case Type1, Type2, Type3
}
enum SecondEnum: String {
case Type1, Type2, Type3
}
case First(FirstEnum)
case Second(SecondEnum)
var rawValue: String {
switch self {
case .First(let e):
return e.rawValue
case .Second(let e):
return e.rawValue
}
}
}
IteratorManager.swift:
class IteratorManager {
var enumsArray = [MyEnums]()
func iterate() {
for e in enumsArray {
print(e.rawValue)
}
}
}
填充数组并迭代:
let iteratorManager = IteratorManager()
iteratorManager.enumsArray = [MyEnums.First(MyEnums.FirstEnum.Type1), MyEnums.Second(MyEnums.SecondEnum.Type2)]
iteratorManager.iterate()
它也是类型安全的(不像Any的解决方案)。
此外,我们可以定义一个示例协议:
protocol MyEnumsProtocol {
var processedValue: String { get }
static func typeGeneralDescription() -> String
}
实现它:
enum MyEnums {
enum FirstEnum: String, MyEnumsProtocol {
case Type1, Type2, Type3
var processedValue: String {
return "-=(self)-="
}
static func typeGeneralDescription() -> String {
return "First enum type"
}
}
enum SecondEnum: String, MyEnumsProtocol {
case Type1, Type2, Type3
var processedValue: String {
return "-=(self)-="
}
static func typeGeneralDescription() -> String {
return "Second enum type"
}
}
case First(FirstEnum)
case Second(SecondEnum)
var rawValue: String {
switch self {
case .First(let e):
return e.rawValue
case .Second(let e):
return e.rawValue
}
}
var subTypeDesc: String {
switch self {
case .First(let e):
return "(FirstEnum.typeGeneralDescription()): (e.processedValue)"
case .Second(let e):
return "(SecondEnum.typeGeneralDescription()): (e.processedValue)"
}
}
}
并像这样使用:
let subTypeDesc = iteratorManager.enumsArray.first?.subTypeDesc