Swift by example protocols

 
AKA Interfaces in other languages:
 
abstract properties and methods that
 
concrete classes implement.

import Foundation

protocol Image {
    // Protocol defines only a properties'
    // type and whether it's gettable or settable
    var filename: String { get set }
    var filesize: Double { get }
    var mimetype: String { get }
    var height: Double { get }
    var width: Double { get }

    /*    class var someTypeProperty: Int { get set } */

    func save ()

    mutating func resize(width: Double, height: Double)
}

Structs can adopt protocols...

struct Gif : Image {
    var filename: String
    var filesize: Double
    var mimetype = "image/gif"
    var height: Double
    var width: Double

    func save() {

    }

    mutating func resize(width: Double, height: Double) {

    }
}

...or Classes can adopt protocols...

class Png : Image {
    var filename: String
    var filesize: Double
    var mimetype = "image/png"
    var height: Double
    var width: Double

    init(filename: String, filesize: Double, width: Double, height: Double) {
        self.filename = filename
        self.filesize = filesize
        self.width = width
        self.height = height
    }

    func save() {

    }

    // `mutating` is not required when the protocol already
    // declares it as such.
    func resize(width: Double, height: Double) {

    }
}

var gif = Gif(filename: "rainbow.gif", filesize: 2.3, mimetype: "image", height: 50, width: 50)
var png = Png(filename: "carry.png", filesize: 3.4, width: 100, height: 54)


Protocols are full-fledged types

func resizeImage (var img: Image) {
    img.resize(50.0, height: 50.0)
}

Protocols are heavily used as part of the delegate pattern
 
so that classes can call delegates' hook methods during certain
 
lifecycle events.
 

# Protocol Composition

 
A type can be composed of multiple protocols.

protocol Video {
    var framerate: Int { get }
    var resolution: Double { get }
}


struct Media: Image, Video {
    var filename: String
    var filesize: Double
    var mimetype: String
    var height: Double
    var width: Double
    var framerate: Int
    var resolution: Double

    func save() {

    }

    func resize(width: Double, height: Double) {

    }
}

Each protocol is comma-separated within brackets.
func save(media: protocol<Image, Video>) {
    media.save()
}

# Protocol Checking

 
is and as work as on any other type.
 

# Optional Protocol Requirements

 
Denoted with @optional.
 
This feature requires protocols be marked
 
with @objc, which exposes the protocol
 
to Objective-C code.
@objc protocol Time {
    var day: Int { get }
    var month: Int { get }
    var year: Int { get }
    optional var hour: Int { get }
    optional var minute: Int { get }
    optional var second: Int { get }

    func toString () -> String
}

class ShortDate : Time {
    @objc var day: Int
    @objc var month: Int
    @objc var year: Int

    init(day: Int, month: Int, year: Int) {
        self.day = day
        self.month = month
        self.year = year
    }

    @objc func toString () -> String {
        return "\(day)/\(month)/\(year)"
    }
}

class LongDate : ShortDate {
    var hour: Int = 0
    var minute: Int = 0
    var second: Int = 0

    convenience init(day: Int, month: Int, year: Int, hour: Int, minute: Int, second: Int) {
        self.init(day: day, month: month, year: year)
        self.hour = hour
        self.minute = minute
        self.second = second
    }

    override func toString() -> String {
        return super.toString() + " \(hour):\(minute):\(second)"
    }
}

var dates: [AnyObject] = [
    ShortDate(day: 5, month: 5, year: 2016),
    LongDate(day: 5, month: 5, year: 2016, hour:10, minute:1, second: 0)
]

for item in dates {
    let date = item as! Time

    print("\(date.toString())")                              // 5/5/2016 5/5/2016 10:1:0

    if let hours = date.hour {
        print("Hour of the day: \(hours)")                  // Hour of the day: 10
    }
}