Skip to content

What is Initializers and what are its different types?

1. Designated Initializers:

  • Designated initializers are the primary initializers for a class, structure, or enumeration.
  • A class, structure, or enumeration must have at least one designated initializer.

Enum:

  1. Enums in Swift don't support stored properties like classes and structs, so they don't require initializers in the same way.
  2. However, you can define associated values for enum cases, and those associated values can be initialized.
struct Point {
    var x: Double
    var y: Double

    // Designated initializer
    init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }

    // Method to display information
    func displayInfo() {
        print("Point coordinates: (\(x), \(y))")
    }
}

// Creating an instance using the designated initializer
let point1 = Point(x: 3.0, y: 5.0)

// Accessing properties and methods of the instance
point1.displayInfo() // Output: Point coordinates: (3.0, 5.0)
class Point {
    var x: Double
    var y: Double

    // Designated initializer
    init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }

    // Method to display information
    func displayInfo() {
        print("Point coordinates: (\(x), \(y))")
    }
}

// Creating an instance using the designated initializer
let point1 = Point(x: 3.0, y: 5.0)

// Accessing properties and methods of the instance
point1.displayInfo() // Output: Point coordinates: (3.0, 5.0)     
enum DayOfWeek: String {
    case monday, tuesday, wednesday, thursday, friday, saturday, sunday

    // Designated initializer
    init?(dayString: String) {
        switch dayString.lowercased() {
        case "monday":
            self = .monday
        case "tuesday":
            self = .tuesday
        case "wednesday":
            self = .wednesday
        case "thursday":
            self = .thursday
        case "friday":
            self = .friday
        case "saturday":
            self = .saturday
        case "sunday":
            self = .sunday
        default:
            return nil
        }
    }
}

// Creating instances using the designated initializer
if let monday = DayOfWeek(dayString: "Monday"),
let saturday = DayOfWeek(dayString: "saturday"),
let invalidDay = DayOfWeek(dayString: "invalid") {
    print(monday.rawValue)    // Output: monday
    print(saturday.rawValue)  // Output: saturday
    print(invalidDay)         // Output: nil
}

2. Convenience Initializers:

  • Convenience initializers are secondary initializers provided by a class, structure, or enumeration.
  • They are defined with the convenience modifier and are used to create an instance of the type in a simpler or more convenient way.
  • Convenience initializers must call another initializer of the same type using self.init.
struct Point {
    var x: Double
    var y: Double

    // Designated initializer
    init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }

    // Convenience initializer
    init() {
        self.init(x: 0.0, y: 0.0)
    }

    // Method to display information
    func displayInfo() {
        print("Point coordinates: (\(x), \(y))")
    }
}

// Creating instances using the designated and convenience initializers
let point1 = Point(x: 3.0, y: 5.0)     // Designated initializer
let origin = Point()                    // Convenience initializer

// Accessing methods of the instances
point1.displayInfo()  // Output: Point coordinates: (3.0, 5.0)
origin.displayInfo()  // Output: Point coordinates: (0.0, 0.0)

3. Required Initializers:

  • Required initializers are initializers that must be implemented by all subclasses of a class.
  • They are marked with the required modifier.
class Shape {
    var name: String

    // Required initializer
    required init(name: String) {
        self.name = name
    }

    // Method to display information
    func displayInfo() {
        print("Shape: \(name)")
    }
}

class Point: Shape {
    var x: Double
    var y: Double

    // Designated initializer
    init(x: Double, y: Double, name: String) {
        self.x = x
        self.y = y
        super.init(name: name)
    }

    // Required initializer
    required init(name: String) {
        // Default coordinates for points
        self.x = 0.0
        self.y = 0.0
        super.init(name: name)
    }

    // Method to display information
    override func displayInfo() {
        super.displayInfo()
        print("Coordinates: (\(x), \(y))")
    }
}

// Creating instances using required initializers
let origin = Point(name: "Origin")
let point1 = Point(x: 3.0, y: 5.0, name: "Point 1")

// Accessing methods of the instances
origin.displayInfo()  // Output: Shape: Origin, Coordinates: (0.0, 0.0)
point1.displayInfo()  // Output: Shape: Point 1, Coordinates: (3.0, 5.0)

4. Failable Initializers:

  • Failable initializers are initializers that may fail to initialize an instance due to invalid input or other conditions.
  • They are defined with the init? keyword.
  • Failable initializers return an optional instance (Self? or Type?).
  • If initialization fails, the initializer returns nil.
struct Point {
    var x: Double
    var y: Double

    // Failable initializer
    init?(x: Double, y: Double) {
        // Check if the provided coordinates are valid
        guard x.isFinite && y.isFinite else {
            return nil // Return nil if coordinates are not finite
        }

        self.x = x
        self.y = y
    }

    // Method to display information
    func displayInfo() {
        print("Point coordinates: (\(x), \(y))")
    }
}

// Creating instances using the failable initializer
if let validPoint = Point(x: 3.0, y: 5.0),
   let invalidPoint = Point(x: Double.infinity, y: Double.nan) {
    validPoint.displayInfo()   // Output: Point coordinates: (3.0, 5.0)
    invalidPoint.displayInfo() // No output (instance creation failed)
}

5. Implicitly Unwrapped Failable Initializers:

  • Similar to failable initializers, these initializers return an optional instance (Self? or Type?).
  • However, they are implicitly unwrapped, meaning you can use the instance without unwrapping it.
  • They are defined with the init! keyword.

6. Convenience Failable Initializers:

  • Convenience failable initializers combine the behavior of convenience and failable initializers.
  • They are defined with the convenience init? keyword.

7. Required Failable Initializers:

  • Similar to required initializers, these initializers are required to be implemented by all subclasses.
  • They are defined with the required init? keyword.

Let's grow together 🌱

Cheers 🍻