【问题标题】:Swift initialise property at struct initialisation without initialiser没有初始化器的结构初始化时的 Swift 初始化属性
【发布时间】:2020-03-05 19:25:39
【问题描述】:

在 swift 中,结构有一个自动生成的成员初始化器。

这意味着无需我编写 init 即可初始化以下结构。

struct Activity  {
    
    let name: String
    let desc: String
    
    let category: Category
    let subcategory: Subcategory
    let emoji: Character
    
    let coordinate: CLLocationCoordinate2D
    
    let creationTime: Date = Date()
    let activityTime: Date
    
    let id: UUID = UUID()
    
    var comments: [Comment] = []
}

我有一个名为emoji 的属性,由子类别计算得出。换句话说,emoji 的值取决于subcategory 的值。

然而这意味着emoji的值只能在subcategory初始化之后赋值。

我应该如何在代码中做到这一点?

方法一:

提供我自己的初始化程序

init(name: String, desc: String, category: Category, subcategory: Subcategory,
     coordinate: CLLocationCoordinate2D, activityTime: Date) {
    self.name = name
    self.desc = desc
    self.category = category
    self.subcategory = subcategory
    self.coordinate = coordinate
    self.activityTime = activityTime
    self.emoji = AllCategories.categories[category]?[subcategory] ?? "❌"
}

我不喜欢这种方法,因为它添加了许多不必要的代码,这些代码只有在我添加更多属性时才会增长……我想使用生成的结构初始化程序。另一方面,代码还是很简单的。

方法二:

使用仅在调用时计算的lazy var

lazy var emoji: Character = {
     AllCategories.categories[category]?[subcategory] ?? "❌"
}()

我也不太喜欢这种方法,我发现它对于我想要做的事情来说过于复杂。这也使得emojia var而不是let它不是,我希望它保持不变。另一方面,我可以继续使用自动生成的初始化程序。

问题:

  1. 我还有什么其他可能性?
  2. 如果没有,这两种方法中哪一种最好?

【问题讨论】:

  • 虽然我倾向于将@Sweeper 的答案与计算属性一起使用,但使用lazy var 并没有什么特别的错误——Apple 在关于初始化的 Swift 文档中提到以这种方式使用它。

标签: swift struct initialization


【解决方案1】:

这听起来像是一个使用计算属性的好机会:

var emoji: Character {
     AllCategories.categories[category]?[subcategory] ?? "❌"
}

虽然它被声明为var,但您实际上无法设置它。这就是必须声明计算属性的方式。

每次使用该属性时都会计算表达式AllCategories.categories[category]?[subcategory] ?? "❌"。这不是一个太耗时的表达式,所以 IMO 很好。

【讨论】:

  • 我忘记在我的方法中提到这一点,但我也考虑了计算属性,但是我排除了它们,因为它们每次都被评估。一旦我有很多活动和大量类别,您确定这没有问题吗?每次显示活动时,它都必须在字典中找到一个键,这对我来说似乎效率不高。
  • @charel-f 访问字典中的值是 O(1) 时间。它不进行线性搜索。
  • @charel-f 另外,不要过早优化。首先尝试使用计算属性,然后使用分析器查看是否实际上是字典访问使您的应用程序变慢。很有可能,这是另一回事。
  • 感谢您的提示。我的应用程序并不慢(还),但是我想要一些健壮且可扩展的代码,我只是不确定每次评估属性所增加的复杂性虽然很小,但是否值得仅仅包括相当无用的初始化程序。
  • 每次都评估属性不会使您的代码不健壮或不可扩展。正如我所说,字典访问的时间复杂度为 O(1),因此无论您拥有多大的字典,访问它都将花费相同的时间。编写初始化程序是不可扩展的,因为每次添加新属性时都必须向初始化程序添加新行。 @charel-f
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-23
  • 2023-04-02
  • 2015-03-04
  • 1970-01-01
相关资源
最近更新 更多