为多个枚举创建一个DRY函数(枚举子类?

问题描述 投票:0回答:2

我有多个枚举,这些枚举都将共享一个相同的函数。有什么方法可以将这个函数写一次,然后让它出现在所有指定的枚举中?下面是一个例子。

enum CustomerTypes: Int, CaseIterable {
    case NewCustomer = 0
    case ExistingCustomer
    case Myself

    private var title: String {
        switch self {
        case .NewCustomer : return StandardStrings.NewDrive.NewCustomer.string
        case .ExistingCustomer : return StandardStrings.NewDrive.ExistingCustomer.string
        case .Myself : return StandardStrings.NewDrive.Myself.string
        }
    }

    static var titles: [String] {
        get {
            var toReturn: [String] = []
            for value in allCases {
                toReturn.append(value.title)
            }

            return toReturn
        }
    }
}

enum EnquiryTypes: Int, CaseIterable {
    case Phone = 0
    case FaceToFace

    private var title: String {
        switch self {
        case .Phone : return StandardStrings.Misc.Phone.string
        case .FaceToFace : return StandardStrings.Misc.FaceToFace.string
        }
    }

    static var titles: [String] {
        get {
            var toReturn: [String] = []
            for value in allCases {
                toReturn.append(value.title)
            }

            return toReturn
        }
    }
}

如你所见,两个枚举都有相同的 "标题 "变量。有什么方法可以让我创建一个枚举类,让它们可以继承这个函数?

以下是我尝试过的一些方法。 你能扩展一个枚举吗? 我考虑过这个问题,但我不想扩展所有有Int rawValues的函数。

我考虑过创建一个协议,然后创建一个函数,像这样接受协议,但我仍然需要在每个枚举上实现_allCases(因为你不能从CaseIterable继承)。

protocol RBEnum {
    var title: String { get }
    var _allCases: [RBEnum] { get }
}

所以有什么办法可以避免在这些枚举上违反DRY原则?

swift enums dry
2个回答
1
投票

协议是正确的方法。不知道为什么你认为协议不能相互继承,但它们可以,所以你可以让你的协议继承于 CaseIterable.

你也可以大大简化 titled 借用 map 而非 for..in 循环,摆脱无用的 get 指定符。getter是计算属性的默认访问器,你不需要将闭包包在 get { ... } 除非你同时创建一个getter和setter。

protocol Titled: CaseIterable {
    var title: String { get }
    static var titles: [String] { get }
}

extension Titled {
    static var titles: [String] { allCases.map(\.title) }
}

那么你只需要保留 title 属性,并使它们符合 Titled 而由于默认的实现,你会得到 titles 免费的。

与你的问题无关,但enum case应该像所有变量一样是 lowerCamelCase。

enum CustomerTypes: Int, Titled {
    case newCustomer = 0
    case existingCustomer
    case myself

    var title: String {
        switch self {
        case .newCustomer : return "new"
        case .existingCustomer : return "existing"
        case .myself : return "my"
        }
    }
}

enum EnquiryTypes: Int, Titled {
    case phone = 0
    case faceToFace

    var title: String {
        switch self {
        case .phone : return "phone"
        case .faceToFace : return "face"
        }
    }
}

0
投票

例如,你可以使用一个自定义协议。

protocol HasTitle: CaseIterable {
    var title: String { get }
}

extension HasTitle {
    static var titles : [String] { allCases.map { $0.title } }
}

然后使你的枚举符合你的新协议。

enum CustomerTypes: Int, HasTitle {
    case NewCustomer = 0
    case ExistingCustomer
    case Myself

    private var title: String {
        switch self {
        case .NewCustomer : return StandardStrings.NewDrive.NewCustomer.string
        case .ExistingCustomer : return StandardStrings.NewDrive.ExistingCustomer.string
        case .Myself : return StandardStrings.NewDrive.Myself.string
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.