在 Swift 中使用嵌套初始化器是不好的做法吗?

Is using nested initializers in Swift bad practice?

假设我有这样的 Swift struct 设置:

struct User {
    // Properties
    var name: String?
    var username: String!
    var email: String?
}

现在,在我看来,有两种设计初始化程序的方法。

这是第一个:

init(username: String) {
    self.username = username
}

init(username: String, name: String) {
    self.username = username
    self.name = name
}

init(username: String, name: String, email: String) {
    self.username = username
    self.name = name
    self.email = email
}

这是第二个:

init(username: String) {
    self.username = username
}

init(username: String, name: String) {
    self.init(username: username)
    self.name = name
}

init(username: String, name: String, email: String) {
    self.init(username: username, name: name)
    self.email = email
}

哪种做法更好,甚至有什么不同吗?

这是不正确的。根据 Apple 文档,如果您想制作多个执行相同操作的初始化程序,您可以使用这样的便利初始化程序。便利初始化器最终会调用指定的初始化器。

convenience init(username: String?) {
    self.init(username: username, name: nil)
}

convenience init(username: String?, name: String?) {
    self.init(username: username, name: name, email: nil)
}

// designated initializer
init(username: String?, name: String?, email: String?) {
    self.init(username: username, name: name)
    self.email = email
}

现在你可以这样称呼它了

let user = User(username: "john")

let user = User(username: "john", name: "John Doe")

let user = User(username: "john", name: "John Doe", email: "johndoe@domain.com")

实际上你只需要一个初始化程序。

username好像是必须的,所以声明为非可选的。

如果您为其他参数提供默认值,则可以省略它们。

struct User {
  // Properties
  var name: String?
  var username : String
  var email: String?

  init(username: String, name: String? = nil, email: String? = nil) {
    self.username = username
    self.name = name
    self.email = email
  }
}

现在你可以通过一个初始化器使用这三种形式

User(username: "Foo")
User(username: "Foo", name: "Bar")
User(username: "Foo", name: "Bar", email:"john@doe.com")

在这种情况下,我建议将所有属性声明为非可选属性。值的缺失可以用空字符串表示,您永远不必处理可选绑定或强制解包。

struct User {
  // Properties
  var name, username, email : String

  init(username: String, name: String = "", email: String = "") {
  ...

初始化器的行为完全相同