任何类型的可选扩展
Optional extension for any types
我想为 任何 类型编写 Optional
扩展。
我的整数代码:
extension Optional where Wrapped == Int {
func ifNil<T>(default: T) -> T {
if self != nil {
return self as! T
}
return default
}
}
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
等
你有什么建议?
可选 已经 通用。它已经接受任何类型作为其参数化类型。它的参数化已经 有 名称: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
您的基本问题的答案是删除 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)
我想为 任何 类型编写 Optional
扩展。
我的整数代码:
extension Optional where Wrapped == Int {
func ifNil<T>(default: T) -> T {
if self != nil {
return self as! T
}
return default
}
}
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
等
你有什么建议?
可选 已经 通用。它已经接受任何类型作为其参数化类型。它的参数化已经 有 名称: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
您的基本问题的答案是删除 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)