gpt4 book ai didi

Swift:初始化具有大量属性的模型类的正确方法

转载 作者:IT王子 更新时间:2023-10-29 05:44:44 25 4
gpt4 key购买 nike

如何使用大量属性初始化类/结构?

这个问题可能在没有 Swift 上下文的情况下被问到,但 Swift 给它带来了 flavor ,所以我在标题和标签中添加了 Swift 标签。

假设您有一个包含 20 个属性的 User 类。他们中的大多数不应为零或为空。让我们假设这些属性不是相互依赖的。假设根据类的逻辑,它的 33% 应该是常量 (let)。假设其中至少 65% 没有有意义的默认值。您将如何设计此类并初始化它的实例?

到目前为止,我的想法很少,但似乎没有一个让我完全满意:

  • 将所有属性线性放入类中并创建巨大的 init 方法:

    class User {
    // there is 20 properties like that
    let id : String
    let username : String
    let email : String
    ...
    var lastLoginDate : Date
    var lastPlayDate : Date

    // then HUUUUGE init
    init(id: String,
    username: String,
    ...
    lastPlayDate: Date) {
    }
    }
  • 尝试将属性分组为子类型并分别处理较小的 init

    class User {
    struct ID {
    let id : String
    let username : String
    let email : String
    }
    struct Activity {
    var lastLoginDate : Date
    var lastPlayDate : Date
    }
    let id : ID
    ...
    var lastActivity : Activity

    // then not so huge init
    init(id: ID,
    ...
    lastActivity: Activity) {
    }
    }
  • 另一种解决方案是稍微打破要求:要么声明一些可选属性并在 init 之后设置值,要么声明虚拟默认值并在 init 之后设置正常值,这在概念上似乎是相同的

    class User {
    // there is 20 properties like that
    let id : String
    let username : String
    let email : String
    ...
    var lastLoginDate : Date?
    var lastPlayDate : Date?

    // then not so huge init
    init(id: String,
    username: String,
    email: String) {
    }
    }

    // In other code
    var user = User(id: "1", username: "user", email: "user@example.com"
    user.lastLoginDate = Date()

是否有一个很好的范例/模式来处理这种情况?

最佳答案

你可以尝试构建器模式。

例子

class DeathStarBuilder {

var x: Double?
var y: Double?
var z: Double?

typealias BuilderClosure = (DeathStarBuilder) -> ()

init(buildClosure: BuilderClosure) {
buildClosure(self)
}
}

struct DeathStar : CustomStringConvertible {

let x: Double
let y: Double
let z: Double

init?(builder: DeathStarBuilder) {

if let x = builder.x, let y = builder.y, let z = builder.z {
self.x = x
self.y = y
self.z = z
} else {
return nil
}
}

var description:String {
return "Death Star at (x:\(x) y:\(y) z:\(z))"
}
}

let empire = DeathStarBuilder { builder in
builder.x = 0.1
builder.y = 0.2
builder.z = 0.3
}

let deathStar = DeathStar(builder:empire)

示例取自此处:https://github.com/ochococo/Design-Patterns-In-Swift

如果您正在寻找更像 Java 的解决方案,您可以尝试类似的方法。

替代示例

final class NutritionFacts {
private let servingSize: Int
private let servings: Int
private let calories: Int
private let fat: Int
private let sodium: Int
private let carbs: Int

init(builder: Builder) {
servingSize = builder.servingSize
servings = builder.servings
calories = builder.calories
fat = builder.fat
sodium = builder.sodium
carbs = builder.carbs
}

class Builder {
let servingSize: Int
let servings: Int

private(set) var calories = 0
private(set) var fat = 0
private(set) var carbs = 0
private(set) var sodium = 0

init(servingSize: Int, servings: Int) {
self.servingSize = servingSize
self.servings = servings
}

func calories(value: Int) -> Builder {
calories = value
return self
}

func fat(value: Int) -> Builder {
fat = value
return self
}

func carbs(value: Int) -> Builder {
carbs = value
return self
}

func sodium(value: Int) -> Builder {
sodium = value
return self
}

func build() -> NutritionFacts {
return NutritionFacts(builder: self)
}
}
}

let facts = NutritionFacts.Builder(servingSize: 10, servings: 1)
.calories(value: 20)
.carbs(value: 2)
.fat(value: 5)
.build()

示例取自:http://ctarda.com/2017/09/elegant-swift-default-parameters-vs-the-builder-pattern

关于Swift:初始化具有大量属性的模型类的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42201720/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com