Swift使用可选的存储属性初始化Struct

时间:2016-05-31 19:00:20

标签: ios swift

我是一名Swift新手,我正试图使用​​带有可选属性的Structs。我已经做了很多搜索并得到了一些有效的东西,但感觉非常低效,所以想知道是否有更好/更易于管理的方式来实现我的目标。

我想使用Structs来代表一家公司,但我事先并不知道任何特定业务可能具有哪些属性组合。这似乎意味着我必须为每个可能的参数组合创建一个init()。

这是一个简化的例子(我有更多属性):

import Foundation

struct Business {
    let name : String
    var web : String?
    var address: String?

    // just the business name
    init(busName: String) {
        self.name = busName
    }

    // business name + website
    init(busName: String, website: String) {
        self.name = busName
        self.web = website
    }

    // business name + address
    init(busName: String, address: String) {
        self.name = busName
        self.address = address
    }

    // business name + website + address
    init(busName: String, website: String, address: String) {
        self.name = busName
        self.web = website
        self.address = address
    }
}

然后我可以像这样初始化类:

Business(busName: "Dave's Cafe", website: "http://www.davescafe.com")

Business(busName: "Sarah's Brewhouse", address: "41 Acacia Ave, Smalltown")

有没有办法创建某种init(),其中参数是可选的?如果你可以指向我的术语或概念的方向来搜索那将是伟大的。

3 个答案:

答案 0 :(得分:49)

使用默认值:

init(busName: String, website: String? = nil, address: String? = nil) {
    self.name = busName
    self.web = website
    self.address = address
}

然后你可以像这样调用init:

_ = Business(busName: "Foo")
_ = Business(busName: "Foo", website: "www.foo.bar")
_ = Business(busName: "Foo", address: "bar")
_ = Business(busName: "Foo", website: "www.foo.bar", address: "bar")

答案 1 :(得分:8)

您可以从其他OOP语言借用的一种方法是参数构建器模式。从一个返回构建器的静态方法开始,然后为各个参数添加方法,最后调用build()

let bakery = Business
    .withName("Black Forest")
    .andWebSite("www.blackforest.com")
    .andAddress("1 Main St, Springfield, IA 98765")
    .build()

这是一个支持这种API的骨架实现:

class Business {
    // Users never call this init, it's for the builder to use
    init(name: String, webSite: String?, address: String?) {
        ...
    }
    // Here is the method the users call:
    static func withName(name: String) {
        return BusinessBuilder(name)
    }
    // This class collects parameters before calling init
    class BusinessBuilder {
        var name : String
        var webSite : String?
        var address: String?
        func andAddress(address: String) -> BusinessBuilder {
            self.address = address
            return self
        }
        func andWebSite(webSite: String) -> BusinessBuilder {
            self.webSite = webSite
            return self
        }
        func build() -> Business {
            return Business(name, webSite, address)
        }
        init(name: String) {
            self.name = name
        }
    }
}

这使您可以按照您认为合适的任何顺序传递尽可能少的初始化参数,以及在给定情况下您觉得方便的任何顺序。

这种方法的主要用途是当您不知道要获取哪些参数时,例如,当它们来自XML或数据库时。您可以循环调用andXyz方法,然后在没有其他属性设置时调用build()

答案 2 :(得分:0)

希望这对您有帮助

 struct Business {
    let name : String
    var web : String?
    var address: String?


// you also need use question mark in init progress
init(name: String, web: String?, address: String?) {
    self.name = name
    self.web = web
    self.address = address
    }
}

创建对象后,可以在可选值上使用nil 例如:

var newBusiness = Business(name: "AWS", web: nil, address: nil)