微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

swift – 解包/合并多级可选

我正在尝试编写一个函数来解开具有任意数量嵌套级别的选项.这是我正在使用的测试:

let a: Int??? = 1
let b: Int??? = nil
print(a.unwrap(0),b.unwrap(0)) // should print 1,0

我可以使用基本的通用函数获得正确的输出

extension Optional {
    func unwrap<T> (_ defaultValue: T) -> T {
        return (self as? T) ?? defaultValue
    }
}

print(a.unwrap(0),b.unwrap(0)) // 1,0

但这并不妨碍使用与可选类型不同的类型调用函数.例如,我可以调用a.unwrap(“foo”)并打印“foo”而不是“1”,因为当然你不能转换Int ???到String.

我尝试使用Wrapped,它半正确地限制了认值,但没有给出正确的输出

extension Optional {
    func unwrap (_ defaultValue: Wrapped) -> Wrapped {
        return (self as? Wrapped) ?? defaultValue
    }
}

print(a.unwrap(0),b.unwrap(0)) // Optional(Optional(1)),nil

它只展开一个可选的,而不是全部三个,因为nil是Int的有效值?它不会返回认值.

有没有办法安全地做我想要的事情?

解决方法

这段代码符合您的要求.缺点是您需要在要放入选项中的每种类型中实现Unwrappable协议.也许 Sourcery可以帮助你.

protocol Unwrappable {
  associatedtype T

  func unwrap(_ default: T) -> T
}

extension Optional {}

extension Optional: Unwrappable where Wrapped: Unwrappable {
  typealias T = Wrapped.T

  func unwrap(_ defaultValue: T) -> T {
    if let value = self {
      return value.unwrap(defaultValue)
    }
    return defaultValue
  }
}

extension Int: Unwrappable {
  typealias T = Int

  func unwrap(_ default: Int) -> Int {
    return self
  }
}

let nestedOptionalValue: Int??? = 6
let nestedOptionalNil: Int??? = nil
let optionalValue: Int? = 6
let optionalNil: Int? = nil
print(nestedOptionalValue.unwrap(0)) // prints 6
print(nestedOptionalNil.unwrap(0))   // prints 0
print(optionalValue.unwrap(0))       // prints 6
print(optionalNil.unwrap(0))         // prints 0

诀窍在于Unwrappable协议将最终可以解包的类型(如在0,1或更多次展开后展开)标记为某种类型.

这个问题的难点在于,在Optional的扩展中,你可以获得Wrapped类型,但如果Wrapped再次是可选的,你就无法访问Wrapped.Wrapped(换句话说,Swift不支持更高的Kinded类型).

另一种方法是尝试添加一个扩展名为Optional,其中Wrapped == Optional.但是,您还需要更高的类型支持才能访问Wrapped.Wrapped类型.如果我们尝试扩展Optional Wrapped == Optional< T>,我们也会失败,因为我们不能通过T一般扩展Optional.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐