【问题标题】:How to conveniently pass parameters only if they are not nil in swift?只有当它们不是 nil 时,如何方便地传递参数?
【发布时间】:2020-07-17 11:54:50
【问题描述】:

假设我有一个有定义的函数

func someInitialiser(paramA : String = "defaultA", paramB : Int = 23, paramC : Double = 99.99) {

    //initialisation using parameters

}

我不希望函数中的值是可选的,因此在没有给出参数的情况下使用默认值。

但是,当我想调用该函数时,我有一堆值作为参数提供,这些参数确实是可选的。

据我所知,您不能将 nil 值传递给函数并使其回退到默认值,因为该函数不接受可选输入。

所以在我看来,唯一的办法就是

if paramA == nil && paramB == nil && paramC == nil { someInitialiser() }
if paramA == nil && paramB == nil && paramC != nil { someInitialiser(paramC: paramC) }
if paramA == nil && paramB != nil && paramC == nil { someInitialiser(paramB: paramB) }
if paramA == nil && paramB != nil && paramC != nil { someInitialiser(paramB: paramB, paramC: paramC) }
if paramA != nil && paramB == nil && paramC == nil { someInitialiser(paramA: paramA) }
...

对于具有更多参数的函数,它最多有 2^(参数数量)可能的函数调用,因此显然不太好写。

能够做类似的事情会简单得多

someInitialiser(paramA: paramA ?? NULL, paramB: paramB ?? NULL, paramC: paramC ?? NULL)

因此,如果值为 nil,它将根本不向函数传递任何参数,因此它依赖于定义中的默认参数。

我知道另一种方法是在调用函数时也提供默认值,使用类似于上面的合并,尽管不必在定义之外重复它们会很好。

【问题讨论】:

  • 在 Swift 中没有办法说paramA: default。有Optional<Wrapped>.map(_:)Optional<Wrapped>.flatMap(_:),但这可能没什么用。

标签: swift optional optional-parameters optional-arguments


【解决方案1】:

这个扩展很有用。

public extension Optional {

var isNil: Bool {
    switch self {
    case .none:
        return true
    default:
        return false
    }
}

var isSome: Bool {
    switch self {
    case .some:
        return true
    case .none:
        return false
    }
 }

}

let number: Int? = 10
print(number.isSome) // true
print(number.isNil) // false

【讨论】:

  • 与 nil 相比有什么好处?
【解决方案2】:

如果我理解正确的问题,您应该使用?在调用函数或 if 语句(无论你喜欢哪个)之前签名并使用 Nil-Coalescing 运算符

    if yourParameter != nil {
         doSomething
    }

或使用

    yourParameter != nil ? assignValue : assign defaultValue

【讨论】:

    【解决方案3】:

    创建两个函数:

    someInitialiser(paramA: String?, paramB: Int?) {
       someInitializer(paramA: paramA ?? "defaultA", paramB: paramB ?? 23)
    }
    
    someInitialiser(paramA: String, paramB: Int) {
       ...
    }
    

    你真的想多了这个问题。如果您想要nil 的默认值,那么?? 是正确的解决方案。如果不想在函数外使用,那就得让参数可选,在里面使用??

    【讨论】:

    • 也许我是,虽然我想检查我是否正确理解了语义,并且在传递 nil 参数和根本不传递参数时没有等效的概念。我对函数内部选项的问题是,允许 nil 值和默认参数意味着 nil 还必须在函数中设置为默认值,这再次意味着必须维护默认值的 2 个副本。无论如何,该函数确实有很多参数,并且可能会从多个地方调用,所以封闭函数似乎是我正在寻找的。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 2013-07-20
    • 2020-11-03
    • 1970-01-01
    • 2018-10-04
    相关资源
    最近更新 更多