Instruction

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

As you learned in a previous lesson, protocols create a blueprint for defining how a type should look from an API perspective. In a protocol, you define the properties and methods that a type should have. Any type that conforms to that protocol must implement those properties and methods. This enables you to interact with a protocol without requiring knowledge of the actual type.

Defining a Protocol

You define a protocol in Swift with the protocol keyword. For example, this code defines a protocol for a vehicle:

// 1
protocol Vehicle {
  // 2
  var numberOfWheels: Int { get }
  // 3
  var maxSpeed: Double { get }
  // 4
  var totalDistanceTraveled: Double { get set }
  // 5
  func showDetails() -> String
  // 6
  func move(direction: Direction, duration: TimeInterval, speed: Double)
}

Here’s a breakdown of the code snippet:

  1. Defines a protocol called Vehicle that types can conform to. Any type that adopts this protocol must provide implementations for the properties and functions defined within it.
  2. Defines a property on the protocol called numberOfWheels. The property is of type Int, which means it should represent the number of wheels the vehicle has. By including this requirement in the protocol, any type conforming to Vehicle must provide an implementation of this property.
  3. Defines a property called maxSpeed that is a Double. This property indicates the maximum speed the vehicle can achieve.
  4. Defines a property on the protocol called totalDistanceTraveled that is a Double. Note that this property is read-write because it specifies both get and set. numberOfWheels and maxSpeed are read-only because they only specify the get keyword on the property. This means that you can mutate (that is, change) totalDistanceTraveled. Since numberOfWheels and maxSpeed are read-only — also known as immutable — you cannot change them once you’ve set their initial value. This allows you to ensure properties that shouldn’t change can never be changed.
  5. Defines a function on the protocol, showDetails(), that returns a String that provides details about the vehicle when executed.
  6. Defines a function, move(direction:duration:speed:), that takes Direction, TimeInterval and Double as parameters. Direction, in this case, could be a simple enum describing the direction of travel.

Now, when you refer to a Vehicle in your code, you know it has these properties and functions available for you to use. The protocol doesn’t define whether the properties need to be computed properties or stored properties. That’s up to the type that conforms to the protocol.

Conforming to a Protocol

You define a type that implements the protocol as follows:

// 1
class FamilyCar: Vehicle {

  // 2
  let maxSpeed: Double
  let numberOfWheels: Int
  var totalDistanceTraveled: Double
  
  // 3
  init() {
    self.maxSpeed = 50.0
    self.numberOfWheels = 4
    self.totalDistanceTraveled = 0.0
  }
  
  // 4
  func move(direction: Direction, duration: TimeInterval, speed: Double) {

  }
  
  // 5
  func showDetails() -> String {
    "I am a family car"
  }
}

Implementing With Inheritance

Now, compare how you’d implement this using inheritance. To start, you’d define a superclass that matches the protocol:

// 1
open class VehicleType {
  // 2
  let numberOfWheels: Int
  // 3
  var maxSpeed: Double
  var totalDistanceTraveled: Double

  // 4
  init() {
    self.numberOfWheels = 4
    self.maxSpeed = 100
    self.totalDistanceTraveled = 0.0
  }

  // 5
  func move(direction: Direction, duration: TimeInterval, speed: Double) {
    
  }

  // 6
  func showDetails() -> String {
    "I am a vehicle"
  }
}
// 1
class FamilyCarInheritance: VehicleType {
  // 2
  let carMaxSpeed = 50.0
  // 3
  override var maxSpeed: Double {
    get {
      return carMaxSpeed
    }
    set {
      // Do nothing
    }
  }

  // 4
  override func move(direction: Direction, duration: TimeInterval, speed: Double) {
    super.move(direction: direction, duration: duration, speed: speed)
    print("Current distance is \(totalDistanceTraveled)")
  }

  // 5
  override func showDetails() -> String {
    "I am a family car"
  }
}
See forum comments
Download course materials from Github
Previous: Introduction Next: Demo 1