|
|
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
}
}
|