我是一名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(),其中参数是可选的?如果你可以指向我的术语或概念的方向来搜索那将是伟大的。
答案 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)