你能利用 Swift 的默认结构初始值设定项来简化参数传递吗?



我正在设计我们的API,将具体查询对象作为单个参数,而不是爆炸可以传递参数的所有位置的签名。

例如,而不是写这篇...

func someQuery(requiredA:Bool, requiredB:Int, requiredC:String, defaultedA:Bool = false, defaultedB:Int = 1, defaultedC:String = "X", optionalA:Bool? = nil, optionalB:Int? = nil, optionalC:String? = nil){
    ....
}

我正在写这篇...

func someQuery(queryParams:QueryParams){
    ....
}

我正在定义(部分 - 下面)这样的查询对象...;

struct QueryObject{
    let requiredA  : Bool
    let requiredB  : Int
    let requiredC  : String
    let defaultedA : Bool
    let defaultedB : Int
    let defaultedC : String
    let optionalA  : Bool?
    let optionalB  : Int?
    let optionalC  : String?
}

我敢肯定,您可以从名称中分辨出此示例,有些是必需的,有些有默认值,有些是完全可选的。

现在,对于定义Queryparams对象,我正在尝试制作它,因此当他们创建它时,用户只需指定所需的参数,并且可以选择指定其他参数。P>

这就是我追求的...

// At a minimum
let queryParams = QueryParams(requiredA:true, requiredB:1, requiredC:"x")
// Minimums overriding a default
let queryParams = QueryParams(requiredA:true, requiredB:1, requiredC:"x", defaultC:"y")
// Minimums plus an optional, still picking up all defaults
let queryParams = QueryParams(requiredA:true, requiredB:1, requiredC:"x", optionalB:8)

为了实现这一目标,我创建了自己的初始化器,除了内部分配参数外,什么都不做,例如...

struct QueryParams{
    init(
        requiredA  : Bool,
        requiredB  : Int,
        requiredC  : String,
        defaultedA : Bool    = true,
        defaultedB : Int     = 1,
        defaultedC : String  = "x",
        optionalA  : Bool?   = nil,
        optionalB  : Int?    = nil,
        optionalC  : String? = nil
    ){
        self.requiredA  = requiredA
        self.requiredB  = requiredB
        self.requiredC  = requiredC
        self.defaultedA = defaultedA
        self.defaultedB = defaultedB
        self.defaultedC = defaultedC
        self.optionalA  = optionalA
        self.optionalB  = optionalB
        self.optionalC  = optionalC
    }
    let requiredA  : Bool
    let requiredB  : Int
    let requiredC  : String
    let defaultedA : Bool
    let defaultedB : Int
    let defaultedC : String
    let optionalA  : Bool?
    let optionalB  : Int?
    let optionalC  : String?
}

...似乎很多样板代码。我正在尝试找出是否有任何方法可以利用Swift创建结构的默认初始化器,因此我不必手动写所有这些。

注意:

  1. 我在这里选择结构,因为Swift为他们提供了默认的初始化器,而类Afaik不明白。
  2. 显然,所需的参数必须先出现。除此之外,这并不重要(尽管如果必须在定义订单中也可以。我不在乎。)
  3. 成员变量可以是letvar。我只是将let用作习惯。

那么...可以简化/减少/消除此代码?

您无法自行从默认初始化器中获得这种控件。就代码数量最少而言,我会推荐这样的内容。

struct QueryParams{
    let requiredA  : Bool
    let requiredB  : Int
    let requiredC  : String
    var defaultedA : Bool = true
    var defaultedB : Int = 1
    var defaultedC : String = "x"
    var optionalA  : Bool? = nil
    var optionalB  : Int? = nil
    var optionalC  : String? = nil
}
extension QueryParams {
    init(
        requiredA  : Bool,
        requiredB  : Int,
        requiredC  : String
        ){
        self.requiredA  = requiredA
        self.requiredB  = requiredB
        self.requiredC  = requiredC
    }
}

通过将自定义初始化器放入扩展程序中,您可以免费保留默认初始化器。唯一的问题是他们只想自定义一些不需要的属性,初始化后需要进行。