Swift 4中的嵌套枚举

时间:2019-01-13 02:15:53

标签: swift enums

当前从长嵌套枚举中提取数据的实现似乎很繁琐,并且维护此类结构很费力。下面是我拥有的一个实现示例,我只是想输入一些信息,这是否真的是从这些枚举中提取数据的正确方法

import UIKit
import Foundation

enum HousingType {
    case House(HousingSubType)
    case Apartment(HousingSubType)
    case Mansion(HousingSubType)

    enum HousingSubType: CaseIterable {
        case Victorian
        case Modern
        case Standard
    }

    var name: String {
        switch self {
        case let .House(subtype):
            switch subtype {
            case .Modern:
                return Structure.House.Modern.name
            case .Standard:
                return Structure.House.Standard.name
            case .Victorian:
                return Structure.House.Victorian.name
            }
        case let .Apartment(subtype):
            switch subtype {
            case .Modern:
                return Structure.Apartment.Modern.name
            case .Standard:
                return Structure.Apartment.Standard.name
            case .Victorian:
                return Structure.Apartment.Victorian.name
            }
        case let .Mansion(subtype):
            switch subtype {
            case .Modern:
                return Structure.Mansion.Modern.name
            case .Standard:
                return Structure.Mansion.Standard.name
            case .Victorian:
                return Structure.Mansion.Victorian.name
            }
        }
    }

    static var allCases: [HousingType] {
        return
            HousingType.HousingSubType.allCases.map(HousingType.House)
                + HousingType.HousingSubType.allCases.map(HousingType.Apartment)
                + HousingType.HousingSubType.allCases.map(HousingType.Mansion)
    }
}

enum Structure {
    enum House {
        enum Victorian {
            static let name = "Victorian House"
            static let rooms = 4
            static let bathrooms = 1
        }
        enum Modern {
            static let name = "Modern House"
            static let rooms = 4
            static let bathrooms = 4
        }
        enum Standard {
            static let name = "Standard House"
            static let rooms = 4
            static let bathrooms = 2
        }
    }

    enum Apartment {
        enum Victorian {
            static let name = "Victorian Apartment"
            static let rooms = 2
            static let bathrooms = 1
        }
        enum Modern {
            static let name = "Modern Apartment"
            static let rooms = 2
            static let bathrooms = 2
        }
        enum Standard {
            static let name = "Standard Apartment"
            static let rooms = 2
            static let bathrooms = 1
        }
    }

    enum Mansion {
        enum Victorian {
            static let name = "Victorian Mansion"
            static let rooms = 10
            static let bathrooms = 3
        }
        enum Modern {
            static let name = "Modern Mansion"
            static let rooms = 10
            static let bathrooms = 10
        }
        enum Standard {
            static let name = "Standard Mansion"
            static let rooms = 10
            static let bathrooms = 6
        }
    }
}

输出:

for type in HousingType.allCases {
    print(type.name)
}

是:

Victorian House
Modern House
Standard House
Victorian Apartment
Modern Apartment
Standard Apartment
Victorian Mansion
Modern Mansion
Standard Mansion

并输出

let apartment = HousingType.Apartment(.Modern)
print(apartment.name)

是:

Modern Apartment

我可以轻松地从枚举中获取数据并遍历所有情况,但是如您所见,对于单个变量name,每种情况下都要花大量的代码。当我添加代码以获取roomsbathrooms或添加其他HousingSubType时,此实现的长度变得非常长。

是否有更好的方法来获取变量name,而不必通过一系列switch语句显式写出每种可能的情况?尝试拥有一系列各种类型,子类型,子子类型等的静态变量时,我是否应该完全考虑另一种实现?

2 个答案:

答案 0 :(得分:2)

我可能会缺少您真正想做的事情,但是我通常不使用嵌套类型来表示需要动态分析和访问的数据结构。

看到您的示例代码,我将使用Dictionary。

enum HousingType: Hashable {
    case house(HousingSubType)
    case apartment(HousingSubType)
    case mansion(HousingSubType)

    enum HousingSubType: CaseIterable {
        case victorian
        case modern
        case standard
    }

    var name: String {
        return structures[self]!.name
    }

    static var allCases: [HousingType] {
        return
            HousingType.HousingSubType.allCases.map(HousingType.house)
                + HousingType.HousingSubType.allCases.map(HousingType.apartment)
                + HousingType.HousingSubType.allCases.map(HousingType.mansion)
    }
}

struct Structure {
    let name: String
    let rooms: Int
    let bathrooms: Int
}

let structures: [HousingType: Structure] = [
    .house(.victorian): Structure(
        name: "Victorian House",
        rooms: 4,
        bathrooms: 1
    ),
    .house(.modern): Structure(
        name: "Modern House",
        rooms: 4,
        bathrooms: 4
    ),
    .house(.standard): Structure(
        name: "Standard House",
        rooms: 4,
        bathrooms: 2
    ),
    .apartment(.victorian): Structure(
        name: "Victorian Apartment",
        rooms: 2,
        bathrooms: 1
    ),
    .apartment(.modern): Structure(
        name: "Modern Apartment",
        rooms: 2,
        bathrooms: 2
    ),
    .apartment(.standard): Structure(
        name: "Standard Apartment",
        rooms: 2,
        bathrooms: 1
    ),
    .mansion(.victorian): Structure(
        name: "Victorian Mansion",
        rooms: 10,
        bathrooms: 3
    ),
    .mansion(.modern): Structure(
        name: "Modern Mansion",
        rooms: 10,
        bathrooms: 10
    ),
    .mansion(.standard): Structure(
        name: "Standard Mansion",
        rooms: 10,
        bathrooms: 6
    ),
]

答案 1 :(得分:0)

虽然在不了解您要建模的所有信息和使用要求的情况下很难推荐一种方法,但是可以对示例枚举中使用的方法进行一些修改,以减少代码量。

例如,该实现似乎完成了您想要的初始结果(它为HousingType.allCases打印相同的结果,并允许相同的创建和打印单个实例的名称)。但是,它使用略有不同的方法来大大减少所需的代码行:

enum HousingType: CaseIterable {
    case House(HousingSubType)
    case Apartment(HousingSubType)
    case Mansion(HousingSubType)

    enum HousingSubType: String, CaseIterable {
        case Victorian
        case Modern
        case Standard
    }

    static var allCases: [HousingType] {
        return Array(HousingSubType.allCases.map{ [HousingType.House($0), HousingType.Apartment($0), HousingType.Mansion($0) ] }.joined())
    }

    var name: String {
        switch self {
            case .House(let subtype): return subtype.rawValue + " House"
            case .Apartment(let subtype): return subtype.rawValue + " Apartment"
            case .Mansion(let subtype): return subtype.rawValue + " Mansion"
        }
    }
}