首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Swift中,如何指定限制RawRepresentable为字符串的类型别名?

在Swift中,如何指定限制RawRepresentable为字符串的类型别名?
EN

Stack Overflow用户
提问于 2014-08-09 19:33:10
回答 4查看 7.3K关注 0票数 16

我正在尝试定义一个协议,该协议要求实现具有原始值enumString

我不认为目前有可能强制使用enum,而且我也不确定我是否真的关心,只要我能够调用fromRaw()并接收String

因此,我试图保持以下内容的简洁性,同时将Beta限制为原始值为Stringenum

代码语言:javascript
复制
protocol Alpha {
    typealias Beta: RawRepresentable
}

struct Gamma: Alpha {
    enum Beta: String {
        case Delta = "delta"
    }
}

struct Eta<T: Alpha, U: RawRepresentable where T.Beta == U> {
    let alpha: T
    let beta: U
    init(alpha: T, beta: U) {
        self.alpha = alpha
        self.beta = beta
        println("beta is: \(beta.toRaw())")
    }
}

let gamma = Gamma()
Eta(alpha: gamma, beta: .Delta) // "beta is delta"

上面的问题是允许其他原始值,因此这是有效的:

代码语言:javascript
复制
struct Epsilon: Alpha {
    enum Beta: Int {
        case Zeta = 6
    }
}

let epsilon = Epsilon()
Eta(alpha: epsilon, beta: .Zeta) // "beta is 6"

为了解决我目前正在做的事情:

代码语言:javascript
复制
protocol StringRawRepresentable: RawRepresentable {
    class func fromRaw(raw: String) -> Self?
}

protocol Alpha {
    typealias Beta: StringRawRepresentable
}

struct Gamma: Alpha {
    enum Beta: String, StringRawRepresentable {
        case Delta = "delta"
    }
}

// Type 'Epsilon' does not conform to protocol 'Alpha'
struct Epsilon: Alpha {
    enum Beta: Int {
        case Zeta = 6
    }
}

struct Eta<T: Alpha, U: StringRawRepresentable where T.Beta == U> {
    let alpha: T
    let beta: U
    init(alpha: T, beta: U) {
        self.alpha = alpha
        self.beta = beta
        println("beta is: \(beta.toRaw())")
    }
}

let gamma = Gamma()
Eta(alpha: gamma, beta: .Delta) // "beta is delta"

是否可以在typealias原始示例中以不同方式声明RawRepresentable以将RawRepresentable限制为String

更新

指定U: RawRepresentable where U.Raw == String似乎很有希望,所以我尝试了一下:

代码语言:javascript
复制
protocol Alpha {
    typealias Beta: RawRepresentable
}

struct Gamma: Alpha {
    enum Beta: String {
        case Delta = "delta"
    }
}

struct Eta<T: Alpha, U: RawRepresentable where T.Beta == U, U.Raw == String> {
    let alpha: T
    let beta: U
    init(alpha: T, beta: U) {
        self.alpha = alpha
        self.beta = beta

        // Execution was interrupted, reason: EXC_BAD_ACCESS (code=EXC_I386_GPFLT).
        println("beta is: \(beta.toRaw())")
    }
}

let gamma = Gamma()
Eta(alpha: gamma, beta: .Delta) // "beta is delta"

struct Epsilon: Alpha {
    enum Beta: Int {
        case Zeta = 6
    }
}

let epsilon = Epsilon()
Eta(alpha: epsilon, beta: .Zeta) // Error only occurs when this is executed

虽然这在技术上可以防止使用String以外的任何东西,但我正在寻找编译时约束,这似乎会导致运行时异常。

如果可能的话,我也希望由协议强制执行,而不是需要检查.Raw == String的消费者

EN

回答 4

Stack Overflow用户

发布于 2015-12-05 05:47:15

为了添加到这一点上,因为它有点老了,更新后的示例现在在2+中工作,并且在编译时会抱怨.Zeta是不明确的,除非它是字符串类型。

您还可以将检查放入协议扩展的模式匹配中。例如:

代码语言:javascript
复制
extension SequenceType where Generator.Element:RawRepresentable,
                         Generator.Element.RawValue == String {
    func toStringArray() -> [String] {
        return self.map { $0.rawValue }
    }
}
票数 8
EN

Stack Overflow用户

发布于 2018-06-13 08:38:23

这现在应该是可能的。例如,以下协议允许类定义符合字符串的“输入”参数的枚举:

代码语言:javascript
复制
protocol AttributeContainer {
   associatedtype InputKey: RawRepresentable where InputKey.RawValue: StringProtocol
   func set(value: Any?, for inputKey: InputKey)
}

这可用于以下方面:

代码语言:javascript
复制
class MyClass: AttributeContainer {

    enum AttributeKey: String {
       case attributeA, attributeB, attributeC
    }

    func set(value: Any?, for inputKey: InputKey) {
        // Handle the setting of attributes here
    }

}

这类似于苹果在Codable协议中处理Codable的方式。在数据库中存储任意类类型等操作时,我发现它很有用。

票数 3
EN

Stack Overflow用户

发布于 2014-08-10 17:09:34

让我们看看我们的选择。首先,它(在Xcode 6 beta 5中)是众所周知的限制,我们不能以简单和预期的方式指定枚举类型约束。其次,您需要非常清楚的东西:能够调用fromRaw(String)。第三,您需要一个编译器错误。我想说,您最好的选择是编写一个协议来做到这一点,并将确保S/他为您提供fromRaw(String)的要求推给消费者。在本例中,下面是我要做的,简化了第二个代码片段:

代码语言:javascript
复制
protocol Alpha {
    typealias Beta: RawRepresentable
    func fromRaw(raw: String) -> Beta?
}

struct Gamma: Alpha {
    enum Beta: String {
        case Delta = "delta"
        case Omega = "omega"
    }
    func fromRaw(raw: String) -> Beta? {
        return Beta.fromRaw(raw)
    }
}

struct Eta<T: Alpha, U: RawRepresentable where T.Beta == U> {
    let alpha: T
    let beta: U
    init(alpha: T, beta: U) {
        self.alpha = alpha
        self.beta = beta
        println("beta is: \(beta.toRaw())")
    }
}

let gamma = Gamma()
let a = Eta(alpha: gamma, beta: .Delta) // "beta is delta"
println(gamma.fromRaw("delta"))  // Optional(Enum Value)
println(gamma.fromRaw("omega")!) // Enum Value

从哲学上讲,这更符合你的需要:你说:“我想要的不仅仅是RawRepresentable,还有fromRaw(String)。想想你是怎么给我的。”Gamma结构是最简单的例子,消费者详细说明他的枚举,然后说:“好的,我可以给你我的标准fromRaw(),因为它可以工作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25222285

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档