您是否可以利用Swift的结构默认初始化器来简化参数传递?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了您是否可以利用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对象,我试图在创建它时使用它,用户只需要指定所需的参数,并且可以根据需要/看到合适地指定其他参数。

这就是我追求的......

// 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给了他们一个默认的初始化器,而Classes 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
    }
}

通过将自定义初始值设定项放在扩展名中,可以免费保留默认初始化程序。唯一的问题是,如果他们只想定制一些非必需的属性,他们将在初始化后需要这些属性。

以上是关于您是否可以利用Swift的结构默认初始化器来简化参数传递?的主要内容,如果未能解决你的问题,请参考以下文章

协议中的默认初始化程序需要不需要的可变属性

在 Swift 中使用对象初始化器来替换 AllocWithZone

详细讲解 —— 结构体(C语言初阶)

默认情况下,如何将成员初始化程序公开,用于 Swift 中的结构?

C# 结构体

我需要在 Swift 中 memset 一个 C 结构吗?