Engineering

Flexible Constants with Protocol and Generics

Usually, Choices are defined as Enum.

enum Kind {
  case a
  case b
  case c

  var value: Int { ... }
}

class Sample {

  func set(kind: Kind)
}

sample.set(kind: .a)

But, In some case, if Enum has some problems, How do we define? CodingKey in Swift4 uses very good idea.

Define protocol that can get value for choices.

protocol KindDescribing {
  var value: Int { get }
}

Make sample class to generic class.

class Sample<T: KindDescribing> {

  func set(kind: T)
}

Define Enum that conforms to KindDescribing.

enum KindEnum: KindDescribing {
  case a
  case b
  case c

  var value: Int { ... }

We can use it just like this.

let sample = Sample<KindEnum>

sample.set(kind: .a)

In other hands, We can define as Struct that conforms to KindDescribing.

struct KindStruct: KindDescribing {
  let value: Int

  static let a = KindStruct(value: ...)
  static let b = KindStruct(value: ...)
  static let c = KindStruct(value: ...)
  static func custom(value: Int) -> KindStruct {
      return KindStruct(value: value) 
    }
}

We can use this like followings.

let sample = Sample<KindStruct>

sample.set(kind: .a)
sample.set(kind: .custom(value: 100))

This approach will be useful for delegate defining choices.