Understanding Dependency Injection - Swift

Hi, I would like to have a better understanding of Dependency Injection, in general, to start using it.

Based on the three examples below, can someone please point out what would be the pros and the cons of using one over the other?

1 - What problem could Example 1 cause if I don't do unitest? This is my current method.

2- What method of Dependency Injection is best to adopt, Example 2 ro Example 3?

3- I noticed that Example 2 enforces to provided the dependency object at instantiation time whereas Example 3 does not. Couldn't Example 3 create confusion for the programmer since if you don't provide the dependency object, the code will still compile without any warning if you call a function that relies on a method inside the injected object?

Example 1: Without Dependency Injection

class Stereo{
   func volume(){
     print("Adjusting volume...")
   }
}

class Car{
  var stereo = Stereo()

  func adjustVolume(){
    stereo.volume()
  }
}

let car = Car()
car.adjustVolume()

Example 2: With Dependency Injection

class Stereo{
   func volume(){
     print("Adjusting volume...")
   }
}

class Car{
  var stereo: Stereo
  
  init(stereo: Stereo){
    self.stereo = stereo
  }

  func adjustVolume(){
    stereo.volume()
  }
}
let car = Car(stereo: Stereo())
car.adjustVolume()

Example 3: With Optional Dependency Injection

class Stereo{
   func volume(){
     print("Adjusting volume...")
   }
}

class Car{
  var stereo: Stereo?

  func adjustVolume(){
    stereo?.volume()
  }
  // this method can be called without injecting Stereo	
  func someOtherFunction(){
    print("Calling some other function...")
  }
}

let car = Car()
car.stereo = Stereo()
car.adjustVolume()

Thanks

There is no problem with 1.

Between 2 and 3 is a question of coding preference.

Some don't like to have to code an init (2) other don't like to have optionals everywhere (3). But no risk of crash in (3) if you use optionals and do not unwrap. Just the call won't be executed.

What is your's ?

This may provide more indepth understanding of injection: https://www.avanderlee.com/swift/dependency-injection/

I guess my issue is that I'm not seeing the whole picture and it feels like I'm writing a lot more code and making things more complicated for little benefit; at least I don't see the benefit since I don't unitest and I'm a single developer writing small applications. For instance, if we use Example 1 and Example 2 in a SwiftUI view and compare the code, with and without Dependency Injection, Example 2 uses a lot more code and looks more complicated.

Again, I guess I still don't see the benefit of the extra complexity.

Example 1: Without Dependency Injection

class Stereo{
   func volume(){
     print("Adjusting volume...")
   }
}

class Car{
  var stereo =  Stereo()

  func adjustVolume(){
    stereo.volume()
  }
}

struct ContentView: View {
    
    var car = Car()

    var body: some View {
        Button("Adjust Volume"){
            car.adjustVolume()
        }
    }
}

Calling the CarView in other views

CarView()

Example 2: With Dependency Injection

class Stereo{
   func volume(){
     print("Adjusting volume...")
   }
}

class Car{
  var stereo: Stereo
  
  init(stereo: Stereo){
    self.stereo = stereo
  }

  func adjustVolume(){
    stereo.volume()
  }
}

struct CarView: View {
    
    var car: Car
    
    init(car: Car){
        self.car = car
    }
    
    var body: some View {
        Button("Adjust Volume"){
            car.adjustVolume()
        }
    }
}

####Calling the CarView in other views.

CarView(car: Car(stereo: Stereo()))

Understanding Dependency Injection - Swift
 
 
Q