简体   繁体   English

我应该如何使用 Swift 枚举实现默认关联值?

[英]How should I implement Default Associated Values with Swift Enums?

Swift question is there a way of having an enum type with one case that can have an associated value. Swift 问题是有一种方法可以让枚举类型具有一个可以具有关联值的案例。

I have an API that gives me available filters, it's unlikely but possible that the API will add additional filter types.我有一个 API 可以为我提供可用的过滤器,API 不太可能但有可能添加其他过滤器类型。 So if the API sends an unknown filter type I want to keep that information associated with the enum.因此,如果 API 发送未知的过滤器类型,我希望将该信息与枚举相关联。

Below are the different ideas I had about doing this.以下是我对这样做的不同想法。

My first two tries didn't compile.我的前两次尝试没有编译。 My third try just feels a bit clunky.我的第三次尝试只是感觉有点笨拙。

Does anyone have a better way of doing this?有没有人有更好的方法来做到这一点? Do you think I just shouldn't use an enum for this problem?你认为我不应该使用枚举来解决这个问题吗?

typealias APIFilterIdentifier = String

/* Does Not Compile */
enum EnumTestAssociatedValeu: APIFilterIdentifier {
    case Unknown(APIFilterIdentifier)
    case Everyone = "everyone"
    case Team = "myteam"
}

/* Does not compile */
enum EnumTestDefaultAssociatedValues: APIFilterIdentifier {
    case Unknown(APIFilterIdentifier)
    case Everyone(APIFilterIdentifier = "everyone")
    case Team(APIFilterIdentifier = "myteam")
}

/* Compiles but is there a better way? */
enum EnumTestWithCustomInit {

    case Unknown(APIFilterIdentifier)
    case Everyone
    case Team

    init(filterIdentifier: APIFilterIdentifier) {
        let everyone: APIFilterIdentifier = EnumTestWithCustomInit.everyoneFilterIdentifier
        let team: APIFilterIdentifier = EnumTestWithCustomInit.teamFilterIdentifier

        switch filterIdentifier {
        case everyone:
            self = .Everyone
        case team:
            self = .Team
        default:
            self = .Unknown(filterIdentifier)
        }
    }

    func asIdentifer() -> APIFilterIdentifier {
        switch self {
        case .Everyone:
            return EnumTestWithCustomInit.everyoneFilterIdentifier
        case .Team:
            return EnumTestWithCustomInit.teamFilterIdentifier
        case .Unknown(let filterIdentifier):
            return filterIdentifier
        }
    }

    private static var everyoneFilterIdentifier: APIFilterIdentifier {
        return "everyone"
    }

    private static var teamFilterIdentifier: APIFilterIdentifier {
        return "myteam"
    }
}

I know this is a bit old, but would this work for what you want?我知道这有点旧,但是这对你想要的东西有用吗?

typealias FilterIdentifier = String

enum DefaultAPIFilters: FilterIdentifier {
    case Everyone = "everyone"
    case Team = "team"
}

enum APIFilters {
    case Default(DefaultAPIFilters)
    case Custom(FilterIdentifier)
}

let everyoneFilter = APIFilters.Default(.Everyone)
let teamFilter = APIFilters.Default(.Team)
let clownFilter = APIFilters.Custom("clowns_only")

Extending Nathan Perry's response:扩展内森佩里的回应:

You can add a您可以添加一个

var underlyingString: String {
  return getUnderlyingString(self) 
}

to the enum.到枚举。 Then define然后定义

func getUnderlyingString(apiFilter: APIFilters) -> String { 
    switch apiFilter {
    case .Default(let defaultAPIFilter):
        return defaultAPIFilter.rawValue
    case .Custom(let custom):
        return custom
    }
}

According to this answer: Default value for Enum in Swift根据此答案: Swift 中 Enum 的默认值

I recommend using such an approach我建议使用这种方法

public enum Result {
    case passed(hint: String)
    case failed(message: String)

    static let passed: Self = .passed(hint: "")
}


let res: Result = Result.passed

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM