类型受限的可选扩展名对其他类型可见

时间:2018-11-20 11:09:26

标签: swift generics optional

因此,由于无聊不得不手动将可选值设为nil-coalesce,我决定将通用默认值转换为Optional上漂亮且易于使用的扩展名,如下所示:

public extension Optional {
    var exists: Bool { return self != nil }
}

public extension Optional where Wrapped == String {
    var orEmpty: Wrapped { return self ?? "" }
}

public extension Optional where Wrapped == Int {
    var orZero: Wrapped { return self ?? 0 }
}

public extension Optional where Wrapped == Double {
    var orZero: Wrapped { return self ?? 0 }
}

public extension Optional where Wrapped == Float {
    var orZero: Wrapped { return self ?? 0 }
}

public extension Optional where Wrapped == Bool {
    var orFalse: Wrapped { return self ?? false }
}

当我尝试在具有特定类型的可选值上使用它们时,出现我的问题。
我可以对类型为.orZero的变量调用String?并得到以下错误之一:

  

对成员“ orZero”的含糊不清
    '串?'不能转换为“可选”

我想知道为什么Xcode提供了.orZero这样的可选属性,例如有效的自动完成选项?我本以为通用约束会阻止我看到它们。
关于它的价值,我使用的是Xcode 10.1和Swift 4.2

2 个答案:

答案 0 :(得分:1)

.orZero作为自动完成功能提供是一个错误。可以通过使用适当的文字协议重写扩展名来避免这种情况。

public extension Optional where Wrapped: ExpressibleByIntegerLiteral {
    var orZero: Wrapped { return self ?? 0 }
}

public extension Optional where Wrapped: ExpressibleByBooleanLiteral {
    var orFalse: Wrapped { return self ?? false }
}

以这种方式表示,Swift现在可以弄清楚.isZero应该不建议使用,即类型为String?的变量,如果您仍然尝试调用它,它将给出错误信息Type 'String' does not conform to protocol 'ExpressibleByIntegerLiteral'

答案 1 :(得分:-1)

看看this

在您的扩展名中。orZero仅适用于Int,Float,Double。

对于String,您具有.orEmpty。