Вложенные перечисления в Свифт 4 - PullRequest
0 голосов
/ 13 января 2019

Нынешняя реализация извлечения данных из длинных вложенных перечислений представляется довольно утомительной, а обслуживание таких структур трудоемким. Ниже приведен пример реализации, которую я имею и просто хотел получить некоторую информацию о том, действительно ли это правильный способ извлечения данных из этих перечислений

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. Когда я добавляю код для получения rooms или bathrooms, или как дополнительные HousingSubType, длина этой реализации становится чрезвычайно большой.

Есть ли лучший способ получить переменную name без явной записи каждого возможного случая через серию операторов switch? Есть ли какая-то другая реализация, на которую я должен обратить внимание при попытке получить серию статических переменных различных типов, подтипов, подтипов и т. Д.?

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Несмотря на то, что трудно рекомендовать подход без понимания всей информации, которую вы хотите смоделировать, и требований для ее использования, возможно, немного измените подход, который вы используете в своих примерах, чтобы потребовать меньше кода.

Например, эта реализация, похоже, выполняет те же начальные результаты, которые вы искали (она печатает те же результаты для 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"
        }
    }
}
0 голосов
/ 13 января 2019

Я могу упустить что-то, что вы действительно хотите сделать, но я обычно не использую вложенные типы для представления структуры данных, которую необходимо анализировать и получать к ней динамический доступ.

Видя ваш пример кода, я бы использовал словарь.

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
    ),
]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...