我想为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类型,例如Date
,String
Double
等
您有什么建议?
您的基本问题的答案是只删除where
子句:
extension Optional {
// ... the rest is the same
func isNil<T>(value: T) -> T {
if self != nil {
return self as! T
}
return value
}
}
现在它适用于所有可选项。
但是此代码已损坏。如果T
与Wrapped
不同,则会崩溃。因此,您实际上是说可以在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)
可选是已经泛型。 已经将任何类型作为其参数化类型。它的参数化名称已经[[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