Inversion of control (IoC) makes client code depend on an interface or abstraction instead of directly selecting a concrete implementation. The interface acts as a contract for operations, inputs, outputs, types, and behavior, allowing implementations to change behind it. This reduces coupling while improving robustness, readability, and testability. section 1.3.2
IoC works with modularity: interfaces define the boundaries, implementations occupy replaceable parts, and larger functionality can be organized into packages, services, libraries, or subsystems. The technique supports divide-and-conquer design rather than prescribing one object-oriented pattern. section 1.3.2 section 1.4.2
Sensor observation
A thermometer implements the ISensor abstraction, transforms native readings into Celsius, and supplies its name and data type. An Observer receives the sensor and a Receiver, rather than requiring the observing workflow to know the thermometer's implementation. Another implementation can occupy the same interface without changing the client workflow. section 1.3.2
Listing 1.4 Interfaces and inversion of control
final class Receiver extends IConnection { #1
def send(dataType: String, name: String, data: Float) =
server.connection.send(dataType, name, data)
}
final class Thermometer extends ISensor { #2
val correction = -12.5f #3
def transform(data: native.core.Temperature) : Float =
toCelsius(data) + correction
def getName() : String = "T-201A" #4
def getDataType() : String = "temperature"
def getData() : Float = {
val data = native.core.thermometer.getData()
transform(data)
}
}
object Worker { #5
def observeThermometerData() {
val t = new Thermometer()
val r = new Receiver()
val observer = new Observer(t, r) #6
observer.readAndSendData()
}
}
Inspect the annotated listing for the interface-based sensor, receiver, and observer composition. section 1.3.2
IoC also enables isolated tests. Injecting mocked, test-only dependencies separates unit code from external systems; impure functions similarly require interfaces, injected dependencies, and mocks when they depend on the outside world. section 15.1


