ios Swift 使用可选的存储属性初始化结构
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37553626/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swift Initialize Struct with optional stored properties
提问by James
I'm a Swift newbie and I'm trying to get my head around using Structs with optional properties. I've done quite a bit of searching and got something that works but it feels incredibly inefficient so wondered if there's a better/more manageable way of achieving my goal.
我是 Swift 新手,我正在尝试使用带有可选属性的结构体。我已经做了很多搜索并得到了一些有用的东西,但感觉效率非常低,所以想知道是否有更好/更易于管理的方法来实现我的目标。
I'd like to use Structs to represent a business but I have no idea in advance which combination of properties any specific business is likely to have. This seems to mean that I have to create an init() for every possible combination of parameters.
我想使用 Structs 来表示业务,但我事先不知道任何特定业务可能具有哪些属性组合。这似乎意味着我必须为每个可能的参数组合创建一个 init()。
Here's a simplified example (I have many more properties):
这是一个简化的例子(我有更多的属性):
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
}
}
I can then initialise the class like this:
然后我可以像这样初始化这个类:
Business(busName: "Dave's Cafe", website: "http://www.davescafe.com")
Business(busName: "Sarah's Brewhouse", address: "41 Acacia Ave, Smalltown")
Is there no way to create some kind of init() where the parameters are optional? If you could point me in the direction of terms or concepts to search for that would be great.
有没有办法在参数是可选的情况下创建某种 init() ?如果您能指出我要搜索的术语或概念的方向,那就太好了。
回答by dasdom
Use default values:
使用默认值:
init(busName: String, website: String? = nil, address: String? = nil) {
self.name = busName
self.web = website
self.address = address
}
Then you can call the init like this:
然后你可以像这样调用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")
回答by dasblinkenlight
One approach that you can borrow from other OOP languages is parameter builder pattern. Start with a static method that returns a builder, then add methods for individual parameters, and finally call build()
:
您可以从其他 OOP 语言中借用的一种方法是参数构建器模式。从返回构建器的静态方法开始,然后为各个参数添加方法,最后调用build()
:
let bakery = Business
.withName("Black Forest")
.andWebSite("www.blackforest.com")
.andAddress("1 Main St, Springfield, IA 98765")
.build()
Here is a skeletal implementation that enables this kind of an API:
这是启用这种 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
}
}
}
This lets you pass as few or as many initializer parameters as you see fit, in any order that you find convenient in a given situation.
这使您可以按照您认为合适的任何顺序传递尽可能少或尽可能多的初始化程序参数,在给定情况下您认为方便的任何顺序。
The main use of this approach is when you do not know which parameters you are going to get, for example, when they come from an XML or a database. You can call andXyz
methods in a loop, and then call build()
when you have no other attributes to set.
这种方法的主要用途是当您不知道将获得哪些参数时,例如,当它们来自 XML 或数据库时。您可以andXyz
在循环中调用方法,然后build()
在没有其他属性要设置时调用。
回答by Jeffrey
hope this could help you
希望这可以帮助你
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
}
}
Once you create a object you could use nil on your optional value For example :
创建对象后,您可以在可选值上使用 nil 例如:
var newBusiness = Business(name: "AWS", web: nil, address: nil)