使用可选的存储属性快速初始化结构

问题描述 投票:0回答:4

我是 Swift 新手,我正在尝试使用具有可选属性的结构。我做了很多搜索并得到了一些有用的东西,但感觉效率非常低,所以想知道是否有更好/更易于管理的方法来实现我的目标。

我想使用结构来表示业务,但我事先不知道任何特定业务可能具有哪些属性组合。这似乎意味着我必须为每个可能的参数组合创建一个 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() ?如果您能为我指明要搜索的术语或概念的方向,那就太好了。

ios swift
4个回答
82
投票

使用默认值:

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")

我不同意我的话被用来训练 OpenAI。


9
投票

可以从其他 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()


1
投票

希望这可以帮助你

 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)   

1
投票

接受的答案会起作用,但还可以更好。 使用

struct
最好的方法是依赖默认的初始化程序

struct Business { // This is all you need
    let name : String
    var web : String?
    var address: String?

    // Look mom no inits
}

有了这样的结构,就不需要声明初始化器了。默认的

init
拥有您需要的一切:

有一个问题。如果您仍然需要声明额外的初始化程序 - 请在

extension
中执行,否则它将删除默认的 init。

© www.soinside.com 2019 - 2024. All rights reserved.