Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using nested initializers in Swift bad practice?

Say I have a Swift struct setup like this :

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

Now, the way I look at it, there are 2 ways of designing the initializer.

Here's the first:

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
}

Here's the second :

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
}

Which is the better practice and does it even make a difference ?

like image 587
Sam Fischer Avatar asked Dec 08 '25 07:12

Sam Fischer


2 Answers

Actually you need only one initializer at all.

username seems to be required, so declare it as non-optional.

If you provide a default value for the other parameters they could be omitted.

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
  }
}

Now you can use these three forms with one initializer

User(username: "Foo")
User(username: "Foo", name: "Bar")
User(username: "Foo", name: "Bar", email:"[email protected]")

In this case I'd recommend to declare all properties as non-optionals. The absence of a value can be represented with an empty string and you have never to deal with optional bindings or forced unwrapping.

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

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

The behavior of the initializer is exactly the same

like image 104
vadian Avatar answered Dec 09 '25 21:12

vadian


This is not correct. Based on Apple Documentation, if you want to make multiple initializer that does the same thing you could use convenience initializer like this. Convenience initializer will finally call the designated initializer.

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
}

Now you can call it like this

let user = User(username: "john")

or

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

or

let user = User(username: "john", name: "John Doe", email: "[email protected]")
like image 25
Edward Anthony Avatar answered Dec 09 '25 21:12

Edward Anthony