将一个不可失败的初始化器委托给一个可失败的初始化器

10

编辑

感谢@Airspeed Velocity的帮助,我们找到了一个简单的解决方案,由于这是从JSON解析而来,因此添加了一些小变化。允许初始化程序接受AnyObject?并默认为Unknown(或Invalid):

init(value: AnyObject?) {
  if let value = value as? Int
    ,let result = Result(rawValue: value) {
      self = result
  } else {
    self = .Unknown
  }
}
我已经实现了一个带有Unknown选项的枚举类型:
enum Result: Int {
  case Success
  case Failure
  case Foo
  case Bar
  case FooBar
  case FooFoo
  ...
  case Unknown = -1
}

我想创建另一个初始化器,它接受一个 Int 并在枚举类型未识别这种情况时返回 Unknown

init(value: Int) {
  self.init(rawValue: value)
  if self == nil { // Complication Error
    self = .Unknown
  }
}

目前我的解决方案是使用工厂方法,然而初始化器会更加简洁:

static func resultWithValue(value: Int) -> Result {
  if let result = self(rawValue: value) {
    return result
  }
  return .Unknown
}
1个回答

17

虽然你无法委托给可失败的初始化方法,但由于枚举是值类型,你可以尝试使用可失败的初始化方法创建同一枚举类型的另一个值,然后在出现nil情况下替换为默认值,并将其分配给self:

enum Result: Int {
    case Success
    case Failure
    case Unknown = -1

    init(value: Int) {
        self = Result(rawValue: value) ?? .Unknown
    }
}

Result(value: 100) == .Unknown  // returns true

谢谢!我感到有些尴尬,没有想到在初始化器中使用类型名称。 - Yariv Nissim
哈哈!我一直坚持使用 self.init(.... 来使它工作,但是不行。当我看到解决方案只是简单的 self = 等时,感觉很奇怪 :-) 谢谢。 - Trevor
1
如果其他人试图创建一个委托给可失败初始化程序但在失败时停止执行(例如preconditionFailure())的初始化程序,则以下内容有效:init(unsafeValue: Int) { guard let result = Result(rawValue: unsafeValue) else { preconditionFailure("Unsafe value was not a valid result") } self = result } - Nicholas
如果您需要在self =不可用的类上执行此类操作,请参见https://stackoverflow.com/questions/67781425/use-self-in-convenience-initializers-to-delegate-to-jsondecoder-or-factory-m。 - deaton.dg
虽然你不能使用 self.init 这样的语法,但是你可以使用 self = Self(.... 来代替 self = Result(....,尽管这并不一定会使代码更清晰! - Bluby

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接