我想为任何类型编写Optional
扩展名。
我的整数代码:
extension Optional where Wrapped == Int {
func isNil<T>(value: T) -> T {
if self != nil {
return self as! T
}
return value
}
}
var tempInt: Int?
tempInt.isNil(value: 2) /// returns 2
tempInt = 5
tempInt.isNil(value: 2) /// returns 5
这是可行的,但它是Optional(Int)
扩展名(Optional where Wrapped == Int
),我想将此扩展名用于 任何 类型,例如{{1 }},Date
String
等
您有什么建议?
答案 0 :(得分:2)
可选的已经是通用的。 已经已将任何类型作为其参数化类型。它的参数化名称已经 :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
答案 1 :(得分:2)
基本问题的答案是仅删除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)