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

时间:2022-09-20 12:18:15

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. So if the API sends an unknown filter type I want to keep that information associated with the enum.

我有一个API,它给了我可用的过滤器,这是不可能的,但是API可能会添加额外的过滤器类型。因此,如果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?

有人有更好的方法吗?你认为我不应该用enum来解决这个问题吗?

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"
    }
}

2 个解决方案

#1


8  

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")

#2


4  

Extending Nathan Perry's response:

延长Nathan佩里的反应:

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
    }
}

#1


8  

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")

#2


4  

Extending Nathan Perry's response:

延长Nathan佩里的反应:

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
    }
}