为多个枚举创建一个 DRY 函数(枚举子类化?)
Create a DRY function for multiple enums (enum subclassing?)
我有多个枚举,它们都共享相同的功能。有没有办法只写一次这个函数并让它出现在所有指定的枚举中?这是一个例子:
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
}
}
}
正如您在此处看到的,两个枚举共享相同的 "titles" 变量。有没有办法我可以创建一个 enum/class 他们可以从中继承此功能?
以下是我尝试过的一些方法:
我考虑过这个,但我不想扩展所有具有 Int rawValues
的函数
我考虑过创建一个协议,然后创建一个采用这样协议的函数,但我仍然需要在每个枚举上实现 _allCases(因为你不能从 CaseIterable 继承):
protocol RBEnum {
var title: String { get }
var _allCases: [RBEnum] { get }
}
那么有什么想法可以避免违反这些枚举的 DRY 原则吗?
您可以使用自定义协议,例如:
protocol HasTitle: CaseIterable {
var title: String { get }
}
extension HasTitle {
static var titles : [String] { allCases.map { [=10=].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
}
}
}
协议是正确的方法。不知道为什么你认为协议不能相互继承,但它们可以,所以你可以让你的协议继承自 CaseIterable
.
您还可以通过使用 map
而不是 for..in
循环并删除无用的 get
说明符来显着简化 titled
。 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 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"
}
}
}
我有多个枚举,它们都共享相同的功能。有没有办法只写一次这个函数并让它出现在所有指定的枚举中?这是一个例子:
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
}
}
}
正如您在此处看到的,两个枚举共享相同的 "titles" 变量。有没有办法我可以创建一个 enum/class 他们可以从中继承此功能?
以下是我尝试过的一些方法:
我考虑过这个,但我不想扩展所有具有 Int rawValues
我考虑过创建一个协议,然后创建一个采用这样协议的函数,但我仍然需要在每个枚举上实现 _allCases(因为你不能从 CaseIterable 继承):
protocol RBEnum {
var title: String { get }
var _allCases: [RBEnum] { get }
}
那么有什么想法可以避免违反这些枚举的 DRY 原则吗?
您可以使用自定义协议,例如:
protocol HasTitle: CaseIterable {
var title: String { get }
}
extension HasTitle {
static var titles : [String] { allCases.map { [=10=].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
}
}
}
协议是正确的方法。不知道为什么你认为协议不能相互继承,但它们可以,所以你可以让你的协议继承自 CaseIterable
.
您还可以通过使用 map
而不是 for..in
循环并删除无用的 get
说明符来显着简化 titled
。 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 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"
}
}
}