我有多个枚举,这些枚举都将共享一个相同的函数。有什么方法可以将这个函数写一次,然后让它出现在所有指定的枚举中?下面是一个例子。
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原则?
协议是正确的方法。不知道为什么你认为协议不能相互继承,但它们可以,所以你可以让你的协议继承于 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"
}
}
}
例如,你可以使用一个自定义协议。
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
}
}
}