Constraints

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Constraints

When you define a generic function or type, you can set constraints on the types that may be used. Constraints can be protocols or classes, and the syntax is <T: Protocol> or <T: Class>.

<T: Protocol>

The generic function swapValues<T> works with all types, but consider this generic function:

func max<T>(lhs: T, rhs: T) -> T {
  return lhs > rhs ? lhs : rhs
}
func max<T: Comparable>(lhs: T, rhs: T) -> T {
  return lhs > rhs ? lhs : rhs
}
class FamilyCar: Vehicle { ... }
let myCar = FamilyCar()
max(lhs: familyCar, rhs: myCar)
max(lhs: familyCar.maxSpeed, rhs: myCar.maxSpeed)

<T: Class>

Another class in the same module is VehicleType, which has a move method:

class VehicleType { 
  ...
  func move(direction: Direction, duration: TimeInterval, speed: Double) { ... } 
}
func moveAtoB<T: VehicleType>(vehicle: T, locationA: CLLocation, locationB: CLLocation) { ... }

Where Clause

Use where when you need to set more than one constraint, for example, if T must inherit from the VehicleType class and also conform to the Comparable protocol:

<T where T: VehicleType, T: Comparable>  // illustration only
init<S>(_ s: S) where Element == S.Element, S : Sequence
extension Setting {
  mutating func save(from untypedValue: Any) {
    if let value = untypedValue as? T {
      self.value = value
    }
  }
}
extension Setting where T: Decodable {
  mutating func save(from untypedValue: Any) {
    if let value = untypedValue as? T {
      self.value = value
    }
  }
  
  mutating func save(from json: Data) throws {
    let decoder = JSONDecoder()
    self.value = try decoder.decode(T.self, from: json)
  }  
}
extension Setting {
  mutating func save(from untypedValue: Any) {
    if let value = untypedValue as? T {
      self.value = value
    }
  }
  
  mutating func save(from json: Data) throws where T: Decodable {
    let decoder = JSONDecoder()
    self.value = try decoder.decode(T.self, from: json)
  }
}
See forum comments
Download course materials from Github
Previous: Generics Next: Generics - Conclusion