Day 11 – Protocols and Extensions

// protocols

// protocols allow us to tell certain types what properties and
// functions they must have. We create protocols, and classes/structs
// then conform to it.

protocol Identifiable {
    var id: String {get set} // anything conforming to Identifiable will have to have a string called id, which can be set and gotten
    func identify()
}

func displayID(thing: Identifiable) { //param is anything that conforms to Identifiable
    print("My ID is \(thing.id)")
}

// protocols can inherit from other protocols much like classes

protocol ClearlyIdentifiable: Identifiable {
    var socialSecurityNumber: String {get set}
}

func clearlyIdentifyPerson(thing: ClearlyIdentifiable) {
    print("This person's id is \(thing.id) and their SSN is \(thing.socialSecurityNumber).")
}

// we can also merge different protocols to create a new one

protocol NeedsStudying {
    func study()
}

protocol ClearStudent: Identifiable, NeedsStudying { }

// extensions
// with extensions, we can add methods to types that already exist, to
// make them do new things. for instnace we can extend Int to have a
// method returning its square.

extension Int {
    func squared() -> Int {
        return self * self
    }
   
    var isEven: Bool {
        return self % 2 == 0
    }
}

let number: Int = 7
number.squared()

// it is important to note that you cannot have stored properties in
// extension, only computed ones.

number.isEven

// we can do both and extend protocols too!

let beatles = Set(["John", "Paul", "George", "Ringo"])
let elements = ["Wind", "Earth", "Fire"]

extension Collection {
    func summarize() {
        for name in self {
            print(name)
        }
    }
}

beatles.summarize()
elements.summarize()

// protocol-oriented programming
// essentially, we can provide a default implementation for methods
// declared in protocols, using extensions. So, let's say we want to
// create a protocol called "identifiable", members of which have to
// have a method called identify(). We can provide a simple default
// by extending Identifiable like so:

extension Identifiable {
    func identify() {
        print("My id is \(id)")
    }
}

struct User: Identifiable {
    var id: String // if we were to remove this line, Xcode would give us an error as the struct would not conform with Identifiable.
}

let myUser = User(id: "Lawrence")
myUser.identify()

Leave a Reply

Your email address will not be published. Required fields are marked *