【问题标题】:In place of a failable initializer, can you instead have it return a default case?代替可失败的初始化程序,您可以让它返回默认情况吗?
【发布时间】:2018-09-27 17:34:52
【问题描述】:

考虑这个枚举...

enum ServiceValue : String, Decodable {
    case a
    case b
    case c
    case other
}

给定一个字符串'a',你可以获得一个枚举实例,如下所示:

// 'value' is an optional since the initializer is bailable
let value = ServiceValue(rawValue:'a')

我们想要做的不是为未知值(例如“d”或“somethingUnknown”)返回“nil”,而是要返回ServiceValue.other。但是,您不能覆盖初始化程序,因为它不在基类中,而是编译器为此枚举本身生成的。

也就是说,我们尝试自己滚动,就像这样......

init(serviceValue:String){
    self.init(rawValue:serviceValue) ?? self.init(rawValue:"other")
}

...但这不适用于以下错误:

一个不可失败的初始化器不能委托给用“init?”编写的可失败的初始化器“init(rawValue:)”

初始化器委托('self.init')不能嵌套在另一个表达式中

当然我可以简单地写一个静态方法initFrom,像这样……

initFrom(serviceValue:String) -> ServiceValue {
    return ServiceValue(rawValue:serviceValue) ?? ServiceValue(rawValue:"other")
}

...但这是一个工厂方法,不是真正的初始化程序,也不能防止仍在使用init(rawValue: 的人(尽管最后一部分可能很好,因为它会改变预期的行为。在一个完美的世界中,我'会完全隐藏该初始化程序,但同样,您不能在枚举中覆盖初始化程序。)

那么这可以实现吗,还是工厂模式是唯一的出路?

【问题讨论】:

  • init(string: String) { self = ServiceValue(rawValue: string) ?? .other }
  • 除非我误解了某些东西,否则我不确定这是否相同,因为那是关于在对象上初始化 properties 的。在枚举的情况下,它是我试图默认的对象 itself。 (我希望我能看到编译器生成的内容,以便我可以复制它,仍然是一个 init,但具有不同的签名。)
  • Leo,你能把它放在答案中吗?

标签: swift enums swift4 failable


【解决方案1】:

您可以使用以下默认值创建自定义的非错误初始值设定项:

init(string: String) { 
    self = ServiceValue(rawValue: string) ?? .other
}

【讨论】:

  • 只是出于好奇,您知道为什么使用类型名称调用初始化程序有效,而执行 self.init(rawValue:) 则无效吗?
  • @DávidPásztor 我猜这是使用要求两种类型相同的 nil 合并运算符的限制,并且顺便说一句 self.init(rawValue:) 是一个错误的初始化程序,但不返回任何值所以使用 nil 合并运算符没有任何意义
  • 解决方案是 self.init vs ServiceValue.init。您对 self.init 如何没有返回任何内容的解释,而 ServiceValue.init 确实有助于更好地解释这一点。那并能够分配self,我认为这是不可能的,但显然是。
猜你喜欢
  • 2016-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-19
  • 2014-11-19
相关资源
最近更新 更多