任何类型的可选扩展名

问题描述 投票:1回答:2

我想为any类型编写Optional扩展名。

我的整数代码:

extension Optional where Wrapped == Int {

    func ifNil<T>(default: T) -> T {
        if self != nil {
            return self as! T
        }
        return value
    }
}

var tempInt: Int?

tempInt.ifNil(default: 2) /// returns 2


tempInt = 5


tempInt.ifNil(default: 2) /// returns 5

这是可行的,但它是Optional(Int)扩展名(Optional where Wrapped == Int),我想将此扩展名用于any类型,例如DateString Double

您有什么建议?

swift generics optional swift-extensions
2个回答
2
投票

您的基本问题的答案是只删除where子句:

extension Optional { 
    // ... the rest is the same 
    func isNil<T>(value: T) -> T {
        if self != nil {
            return self as! T
        }
        return value
    }
}

现在它适用于所有可选项。

但是此代码已损坏。如果TWrapped不同,则会崩溃。因此,您实际上是说可以在Wrapped

上运行的非泛型函数
extension Optional {
    func isNil(value: Wrapped) -> Wrapped {
        if self != nil {
            return self!  // `as!` is unnecessary
        }
        return value
    }
}

但是这只是??的精心表达(如马特所指出的)

extension Optional {
    func isNil(value: Wrapped) -> Wrapped { self ?? value }
}

除了??更强大。它包括一个自动关闭功能,可以避免评估默认值(除非实际使用该默认值),并且可以throw。在大多数情况下,它也是更惯用的Swift。您可以找到source on github

public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T)
    rethrows -> T {
  switch optional {
  case .some(let value):
    return value
  case .none:
    return try defaultValue()
  }
}

但是我可以想象您可能基于方法的解决方案的情况(它们很奇怪,但是也许有这种情况)。您可以通过将其重写为一种方法来获得它:

extension Optional {
    public func value(or defaultValue: @autoclosure () throws -> Wrapped) rethrows -> Wrapped {
        switch self {
        case .some(let value):
            return value
        case .none:
            return try defaultValue()
        }
    }
}

tempInt.value(or: 2)

2
投票

可选是已经泛型。 已经将任何类型作为其参数化类型。它的参数化名称已经[[has:Wrapped。只需说Wrapped而不是T。您的T Wrapped

extension Optional { func isNil<Wrapped>(value: Wrapped) -> Wrapped { if self != nil { return self as! Wrapped } return value } }
如果出于某些原因确实喜欢T,请使用类型别名。这只是一个名字:

extension Optional { typealias T = Wrapped func isNil<T>(value: T) -> T { if self != nil { return self as! T } return value } }

但是无论如何,您的扩展名是完全没有必要的,因为这是nil-coalescing运算符??已经完成的工作。

var tempInt: Int? tempInt ?? 2 /// returns 2 tempInt = 5 tempInt ?? 2 /// returns 5

© www.soinside.com 2019 - 2024. All rights reserved.