protocol-oriented programming in swift
TRANSCRIPT
![Page 1: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/1.jpg)
1
![Page 2: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/2.jpg)
2
Protocol-oriented programming in SwiftRostyslav KobyzskyiSoftware Engineer16th Nov, 2016
![Page 3: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/3.jpg)
3
1. Classes and problems2. Start with Protocol3. Using Protocols4. Examples5. Questions
Agenda
![Page 4: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/4.jpg)
Dave Abrahams• David Abrahams is a
computer programmer and author
• Abrahams became a member of the C++ Standards Committee in 1996
• In 2013 Abrahams became an employee at Apple Inc, where he is involved in the development of the Swift programming language
![Page 5: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/5.jpg)
Why Protocols?
![Page 6: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/6.jpg)
Classes• Encapsulation• Access Control• Abstraction• Namespace• Expressive Syntax• Extensibility
![Page 7: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/7.jpg)
Classes• Encapsulation• Access Control• Abstraction• Namespace• Expressive Syntax• Extensibility
![Page 8: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/8.jpg)
1. Implicit Sharing
A
B
Data
![Page 9: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/9.jpg)
1. Implicit Sharing
A
B
Data
![Page 10: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/10.jpg)
1. Implicit Sharing
A
B
Data
![Page 11: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/11.jpg)
1. Implicit Sharing
A
B
Data
![Page 12: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/12.jpg)
1. Implicit Sharing
A
B
Ponies
![Page 13: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/13.jpg)
1. Implicit Sharing
B
Ponies
![Page 14: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/14.jpg)
1. Implicit Sharing
B
Ponies
$@#$%?
![Page 15: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/15.jpg)
1. Implicit Sharing• Defensive Copy• Inefficiency• Race Condition• Locks• More Inefficiency• Deadlock• Complexity• Bugs!
![Page 16: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/16.jpg)
Values don’t Share.
That’s a good thingClasses? They overshare…
![Page 17: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/17.jpg)
2. Inheritance
SubclassStoredProperties
Superclass
![Page 18: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/18.jpg)
2. InheritanceOne superclass
SubclassStoredProperties
Superclass
![Page 19: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/19.jpg)
Instance
2. InheritanceOne superclass
Single Inheritance
SubclassStoredProperties
Superclass
![Page 20: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/20.jpg)
Instance
2. InheritanceOne superclass
Single Inheritance
Super class may have Stored Properties
SubclassStoredProperties
SuperclassStoredProperties
![Page 21: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/21.jpg)
Instance
2. InheritanceOne superclass
Single Inheritance
Super class may have Stored Properties
• You must accept them
SubclassStoredProperties
SuperclassStoredProperties
![Page 22: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/22.jpg)
2. InheritanceOne superclass
Single Inheritance
Super class may have Stored Properties
• You must accept them
• Initialization problem
Instance
SubclassStoredProperties
SuperclassStoredProperties
![Page 23: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/23.jpg)
2. InheritanceOne superclass
Single Inheritance
Super class may have Stored Properties
• You must accept them
• Initialization problem
• Don’t break superclass invariants!
Instance
SubclassStoredProperties
SuperclassStoredProperties
![Page 24: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/24.jpg)
2. InheritanceOne superclass
Single Inheritance
Super class may have Stored Properties
• You must accept them
• Initialization problem
• Don’t break superclass invariants!
Know what/how to override (and when not)
Instance
SubclassStoredProperties
SuperclassStoredProperties
![Page 25: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/25.jpg)
3. Lost Type Relationships
class Ordered {
func precedes(other: Ordered) -> Bool
}
func binarySearch(sortedKeys: [Ordered], forKey k: Ordered) -> Int {
var lo = 0, hi = sortedKeys.count
while hi > lo {
let mid = lo + (hi - lo) / 2
if sortedKeys[mid].precedes(k) { lo = mid + 1 }
else { hi = mid }
}
return lo
}
![Page 26: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/26.jpg)
3. Lost Type Relationships
class Ordered {
func precedes(other: Ordered) -> Bool { }
}
![Page 27: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/27.jpg)
3. Lost Type Relationships
class Ordered {
func precedes(other: Ordered) -> Bool
}
{ fatalError(“implement me!”) }
![Page 28: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/28.jpg)
3. Lost Type Relationships
class Ordered {
func precedes(other: Ordered) -> Bool
}
{ fatalError(“implement me!”) } X
![Page 29: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/29.jpg)
3. Lost Type Relationships
class Ordered {
func precedes(other: Ordered) -> Bool
}
class Number: Ordered {
var value: Double = 0
override fund precedes(other: Ordered) -> Bool {
return value < other.value
}
}
{ fatalError(“implement me!”) } X
![Page 30: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/30.jpg)
class Ordered {
func precedes(other: Ordered) -> Bool
}
class Number: Ordered {
var value: Double = 0
override fund precedes(other: Ordered) -> Bool {
return value < other.value
}
}
3. Lost Type Relationships
{ fatalError(“implement me!”) } X
![Page 31: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/31.jpg)
class Ordered {
func precedes(other: Ordered) -> Bool
}
class Number: Ordered {
var value: Double = 0
override fund precedes(other: Ordered) -> Bool {
return value < other.value
}
}
3. Lost Type Relationships
{ fatalError(“implement me!”) } X
![Page 32: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/32.jpg)
class Ordered {
func precedes(other: Ordered) -> Bool
}
class Number: Ordered {
var value: Double = 0
override fund precedes(other: Ordered) -> Bool {
return value < other.value
}
}
3. Lost Type Relationships
{ fatalError(“implement me!”) } X
`Ordered` does not have a member named `value`
![Page 33: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/33.jpg)
`Ordered` does not have a member named `value`
3. Lost Type Relationships
{ fatalError(“implement me!”) } Xclass Ordered {
func precedes(other: Ordered) -> Bool
}
class Label: Ordered { var text: String = “” ... }
class Number: Ordered {
var value: Double = 0
override fund precedes(other: Ordered) -> Bool {
return value < other.value
}
}
![Page 34: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/34.jpg)
class Ordered {
func precedes(other: Ordered) -> Bool
}
class Label: Ordered { var text: String = “” ... }
class Number: Ordered {
var value: Double = 0
override fund precedes(other: Ordered) -> Bool {
return value < (other as! Number).value
}
}
3. Lost Type Relationships
{ fatalError(“implement me!”) } X
![Page 35: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/35.jpg)
A better Abstraction Mechanism• Support value types (and classes)• Support static type relationships (and dynamic dispatch)
• Non-monolithic• Doesn’t impose instance data on models• Doesn’t impose initialization burdens on models• Makes clear what to implement
![Page 36: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/36.jpg)
Swift is Protocol-Oriented
Programming Language
![Page 37: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/37.jpg)
Start with a Protocol
![Page 38: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/38.jpg)
Starting override with Protocols
class Ordered {
func precedes(other: Ordered) -> Bool
}
class Number: Ordered {
var value: Double = 0
override fund precedes(other: Ordered) -> Bool {
return value < other.value
}
}
{ fatalError(“implement me!”) } X
![Page 39: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/39.jpg)
Starting override with Protocols
class Ordered {
func precedes(other: Ordered) -> Bool
}
class Number: Ordered {
var value: Double = 0
override fund precedes(other: Ordered) -> Bool {
return value < (other as! Number).value
}
}
{ fatalError(“implement me!”) } X
![Page 40: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/40.jpg)
Starting override with Protocols
protocol Ordered {
func precedes(other: Ordered) -> Bool
}
class Number: Ordered {
var value: Double = 0
override fund precedes(other: Ordered) -> Bool {
return value < (other as! Number).value
}
}
{ fatalError(“implement me!”) } X
![Page 41: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/41.jpg)
Starting override with Protocols
protocol Ordered {
func precedes(other: Ordered) -> Bool
}
class Number: Ordered {
var value: Double = 0
override fund precedes(other: Ordered) -> Bool {
return value < (other as! Number).value
}
}
{ fatalError(“implement me!”) }
Protocol methods may not have bodies
![Page 42: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/42.jpg)
Starting override with Protocols
protocol Ordered {
func precedes(other: Ordered) -> Bool
}
class Number: Ordered {
var value: Double = 0
override fund precedes(other: Ordered) -> Bool {
return value < (other as! Number).value
}
}
Method does not override any method from superclass
![Page 43: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/43.jpg)
Starting override with Protocols
protocol Ordered {
func precedes(other: Ordered) -> Bool
}
class Number: Ordered {
var value: Double = 0
override fund precedes(other: Ordered) -> Bool {
return value < (other as! Number).value}
}
![Page 44: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/44.jpg)
Starting override with Protocols
protocol Ordered {
func precedes(other: Ordered) -> Bool
}
struct Number: Ordered {
var value: Double = 0
fund precedes(other: Ordered) -> Bool {
return value < (other as! Number).value
}
}
![Page 45: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/45.jpg)
Starting override with Protocols
protocol Ordered {
func precedes(other: Ordered) -> Bool
}
struct Number: Ordered {
var value: Double = 0
fund precedes(other: Ordered) -> Bool {
return value < (other as! Number).value
}
}
![Page 46: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/46.jpg)
Starting override with Protocols
protocol Ordered {
func precedes(other: Ordered) -> Bool
}
struct Number: Ordered {
var value: Double = 0
fund precedes(other: Number) -> Bool {
return value < other.value
}
}
![Page 47: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/47.jpg)
Starting override with Protocols
protocol Ordered {
func precedes(other: Ordered) -> Bool
}
struct Number: Ordered {
var value: Double = 0
fund precedes(other: Number) -> Bool {
return value < other.value
}
}
Protocol requires function ‘precedes’ with type ‘(Oredered)’ -> Boolcandidate has non-matching type (`Number`) -> Bool
![Page 48: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/48.jpg)
Starting override with Protocols
protocol Ordered {
func precedes(other: Self) -> Bool
}
struct Number: Ordered {
var value: Double = 0
fund precedes(other: Number) -> Bool {
return value < other.value
}
}
Self requirement
![Page 49: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/49.jpg)
Using out Protocolfunc binarySearch(sortedKeys: [Ordered], forKey k: Ordered) -> Int {
var lo = 0, hi = sortedKeys.count
while hi > lo {
let mid = lo + (hi - lo) / 2
if sortedKeys[mid].precedes(k) { lo = mid + 1 }
else { hi = mid }
}
return lo
}
![Page 50: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/50.jpg)
Using out Protocolfunc binarySearch(sortedKeys: [Ordered], forKey k: Ordered) -> Int {
var lo = 0, hi = sortedKeys.count
while hi > lo {
let mid = lo + (hi - lo) / 2
if sortedKeys[mid].precedes(k) { lo = mid + 1 }
else { hi = mid }
}
return lo
}
Protocol ‘Ordered’ can only be used as a generic constraint
because if has Self or associated type requirements
![Page 51: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/51.jpg)
Using out Protocolfunc binarySearch(sortedKeys: [Ordered], forKey k: Ordered) -> Int {
var lo = 0, hi = sortedKeys.count
while hi > lo {
let mid = lo + (hi - lo) / 2
if sortedKeys[mid].precedes(k) { lo = mid + 1 }
else { hi = mid }
}
return lo
}
Protocol ‘Ordered’ can only be used as a generic constraint
because if has Self or associated type requirements
![Page 52: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/52.jpg)
Using out Protocolfunc binarySearch<T: Ordered>(sortedKeys: [T], forKey k: T) -> Int {
var lo = 0, hi = sortedKeys.count
while hi > lo {
let mid = lo + (hi - lo) / 2
if sortedKeys[mid].precedes(k) { lo = mid + 1 }
else { hi = mid }
}
return lo
}
![Page 53: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/53.jpg)
Two-world of Protocols
Without Self Requirement With Self Requirement
func precedes(other: Ordered) -> Bool func precedes(other: Self) -> Bool
![Page 54: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/54.jpg)
Two-world of Protocols
Without Self Requirement With Self Requirement
func precedes(other: Ordered) -> Bool
Usable as a typesort(inout a: [Ordered])
func precedes(other: Self) -> Bool
Only usable as a generic constraintsort<T: Ordered>(inout a: [T])
![Page 55: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/55.jpg)
Two-world of Protocols
Without Self Requirement With Self Requirement
func precedes(other: Ordered) -> Bool
Usable as a typesort(inout a: [Ordered])
Every model must deal with all others
func precedes(other: Self) -> Bool
Only usable as a generic constraintsort<T: Ordered>(inout a: [T])
Models are free from interaction
![Page 56: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/56.jpg)
Two-world of Protocols
Without Self Requirement With Self Requirement
func precedes(other: Ordered) -> Bool
Usable as a typesort(inout a: [Ordered])
Every model must deal with all others
Dynamic dispatch
func precedes(other: Self) -> Bool
Only usable as a generic constraintsort<T: Ordered>(inout a: [T])
Models are free from interaction
Static dispatch
![Page 57: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/57.jpg)
Two-world of Protocols
Without Self Requirement With Self Requirement
func precedes(other: Ordered) -> Bool
Usable as a typesort(inout a: [Ordered])
Every model must deal with all others
Dynamic dispatch
Less optimizable
func precedes(other: Self) -> Bool
Only usable as a generic constraintsort<T: Ordered>(inout a: [T])
Models are free from interaction
Static dispatch
More optimizable
![Page 58: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/58.jpg)
A Primitive “Render”struct Renderer {
func moveTo(p: CGPoint) { print(“moveTo(\(p.x), \(p.y))”) }
func lineTo(p: CGPoint) { print(“lineTo(\(p.x), \(p.y))”) }
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat) {
print(“arcAt(\(center), radius: \(radius)),” +
+ “ startAngle: \(startAngle), endAngle: \(endAngle)”)
}
}
![Page 59: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/59.jpg)
Drawableprotocol Drawable {
func draw(randerer: Renderer)
}
![Page 60: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/60.jpg)
Polygonprotocol Drawable {
func draw(randerer: Renderer)
}
struct Polygon: Drawable {
func draw(renderer: Renderer) {
renderer.moveTo(corners.last!)
for p in corners {
renderer.lineTo(p)
}
}
var corners: [CGPoint] = []
}
![Page 61: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/61.jpg)
Circleprotocol Drawable {
func draw(randerer: Renderer)
}
struct Circle: Drawable {
func draw(renderer: Renderer) {
renderer.artAt(center, radius: radius,
startAngle: 0.0, endAngle: twoPi)
}
}
var center: CGPoint
var radius: CGFloat
}
![Page 62: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/62.jpg)
Diagramprotocol Drawable {
func draw(randerer: Renderer)
}
struct Diagram: Drawable {
func draw(renderer: Renderer) {
for f in elements {
f.draw(renderer)
}
}
var elements: [Drawable] = []
}
![Page 63: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/63.jpg)
Test It!var circle = Circle(
center: CGPoint(x: 187.5, y: 333.5),
radius: 93.75
)
![Page 64: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/64.jpg)
Test It!var circle = Circle(
center: CGPoint(x: 187.5, y: 333.5),
radius: 93.75
)
var triangle = Polygon(corners: [
CGPoint(x: 187.5, y: 427.25),
CGPoint(x: 268.69, y: 286.625),
CGPoint(x: 106.31, y: 286.625)
])
![Page 65: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/65.jpg)
Test It!var circle = Circle(
center: CGPoint(x: 187.5, y: 333.5),
radius: 93.75
)
var triangle = Polygon(corners: [
CGPoint(x: 187.5, y: 427.25),
CGPoint(x: 268.69, y: 286.625),
CGPoint(x: 106.31, y: 286.625)
])
var diagram = Diagram(elements: [circle: triangle])
![Page 66: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/66.jpg)
Test It!var circle = Circle(
center: CGPoint(x: 187.5, y: 333.5),
radius: 93.75
)
var triangle = Polygon(corners: [
CGPoint(x: 187.5, y: 427.25),
CGPoint(x: 268.69, y: 286.625),
CGPoint(x: 106.31, y: 286.625)
])
var diagram = Diagram(elements: [circle: triangle])
diagram.draw(Renderer())
![Page 67: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/67.jpg)
Renderer as Protocolstruct Renderer {
func moveTo(p: CGPoint) { print(“moveTo(\(p.x), \(p.y))”) }
func lineTo(p: CGPoint) { print(“lineTo(\(p.x), \(p.y))”) }
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat) {
print(“arcAt(\(center), radius: \(radius)),” +
+ “ startAngle: \(startAngle), endAngle: \(endAngle)”)
}
}
struct Renderer {
func moveTo(p: CGPoint) { print(“moveTo(\(p.x), \(p.y))”) }
func lineTo(p: CGPoint) { print(“lineTo(\(p.x), \(p.y))”) }
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat) {
print(“arcAt(\(center), radius: \(radius)),” +
+ “ startAngle: \(startAngle), endAngle: \(endAngle)”)
}
}
![Page 68: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/68.jpg)
Renderer as Protocolprotocol Renderer {
func moveTo(p: CGPoint) { print(“moveTo(\(p.x), \(p.y))”) }
func lineTo(p: CGPoint) { print(“lineTo(\(p.x), \(p.y))”) }
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat) {
print(“arcAt(\(center), radius: \(radius)),” +
+ “ startAngle: \(startAngle), endAngle: \(endAngle)”)
}
}
struct Renderer {
func moveTo(p: CGPoint) { print(“moveTo(\(p.x), \(p.y))”) }
func lineTo(p: CGPoint) { print(“lineTo(\(p.x), \(p.y))”) }
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat) {
print(“arcAt(\(center), radius: \(radius)),” +
+ “ startAngle: \(startAngle), endAngle: \(endAngle)”)
}
}
![Page 69: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/69.jpg)
Renderer as Protocolprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat)
}
struct Renderer {
func moveTo(p: CGPoint) { print(“moveTo(\(p.x), \(p.y))”) }
func lineTo(p: CGPoint) { print(“lineTo(\(p.x), \(p.y))”) }
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat) {
print(“arcAt(\(center), radius: \(radius)),” +
+ “ startAngle: \(startAngle), endAngle: \(endAngle)”)
}
}
![Page 70: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/70.jpg)
Renderer as Protocolprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat)
}
struct Renderer {
func moveTo(p: CGPoint) { print(“moveTo(\(p.x), \(p.y))”) }
func lineTo(p: CGPoint) { print(“lineTo(\(p.x), \(p.y))”) }
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat) {
print(“arcAt(\(center), radius: \(radius)),” +
+ “ startAngle: \(startAngle), endAngle: \(endAngle)”)
}
}
![Page 71: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/71.jpg)
Renderer as Protocolprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat)
}
struct TestRenderer: Renderer {
func moveTo(p: CGPoint) { print(“moveTo(\(p.x), \(p.y))”) }
func lineTo(p: CGPoint) { print(“lineTo(\(p.x), \(p.y))”) }
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat) {
print(“arcAt(\(center), radius: \(radius)),” +
+ “ startAngle: \(startAngle), endAngle: \(endAngle)”)
}
}
![Page 72: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/72.jpg)
Rendering with CoreGraphicsRetroactive modelingprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat)
}
![Page 73: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/73.jpg)
Rendering with CoreGraphicsRetroactive modelingprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat)
}
![Page 74: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/74.jpg)
Rendering with CoreGraphicsRetroactive modelingprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat)
}
extension CGContext: Renderer {
func moveTo(p: CGPoint) { }
func lineTo(p: CGPoint) { }
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat) { }
}
![Page 75: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/75.jpg)
Rendering with CoreGraphicsRetroactive modeling
extension CGContext: Renderer {
func moveTo(p: CGPoint) {
CGContextMoveToPoint(self, p.x, p.y)
}
func lineTo(p: CGPoint) {
CGContextAddLineToPoint(self, p.x, p.y)
}
func arcAt(center: CGPoint, radius: CGFloat,
startAngler: CGFloat, endAngle: CGFloat) {
let arc = CGPathCreateMutable()
CGPathAddArc(arc, nil, center.x, center.y, radius,
startAngle, endAngle, true)
CGContextAddPath(self, arc)
}
}
![Page 76: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/76.jpg)
Protocols and Generics for TestabilitySo much better than mocksstruct Bubble: Drawable {
func draw(r: Renderer) {
r.arcAt(center, radius, startAngle: 0, endAngle: twoPi)
r.arcAt(highlightCenter, radius: highlightRadius,
startAngle: 0, endAngle: twoPi
)
}
}
![Page 77: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/77.jpg)
Protocols and Generics for TestabilitySo much better than mocksstruct Bubble: Drawable {
func draw(r: Renderer) {
r.arcAt(center, radius, startAngle: 0, endAngle: twoPi)
r.arcAt(highlightCenter, radius: highlightRadius,
startAngle: 0, endAngle: twoPi
)
}
}
struct Circle: Drawable {
func draw(r: Renderer) {
r.arcAt(center, radius, startAngle: 0, endAngle: twoPi)
}
}
![Page 78: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/78.jpg)
Protocols and Generics for TestabilitySo much better than mocksstruct Bubble: Drawable {
func draw(r: Renderer) {
r.circleAt(center, radius)
r.arcAt(highlightCenter, radius: highlightRadius)
}
}
struct Circle: Drawable {
func draw(r: Renderer) {
r.circleAt(center, radius)
}
}
![Page 79: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/79.jpg)
Adding a Circle Primitiveprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func arcAt(
center: CGPoint, radius: CGFloat,
startAngle: CGFloat, endAngle: CGFloat)
)
}
![Page 80: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/80.jpg)
Adding a Circle Primitiveprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func arcAt(
center: CGPoint, radius: CGFloat,
startAngle: CGFloat, endAngle: CGFloat)
)
}
![Page 81: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/81.jpg)
Adding a Circle Primitiveprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func circleAt(center: CGPoint, radius: CGFloat)
func arcAt(
center: CGPoint, radius: CGFloat,
startAngle: CGFloat, endAngle: CGFloat)
)
}
![Page 82: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/82.jpg)
Adding a Circle Primitiveprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func circleAt(center: CGPoint, radius: CGFloat)
func arcAt(
center: CGPoint, radius: CGFloat,
startAngle: CGFloat, endAngle: CGFloat)
)
}
New requirement
![Page 83: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/83.jpg)
Adding a Circle Primitiveprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func circleAt(center: CGPoint, radius: CGFloat)
func arcAt(
center: CGPoint, radius: CGFloat,
startAngle: CGFloat, endAngle: CGFloat)
)
}
extension TestRenderer {
func circleAt(center: CGPoint, radius: CGFloat) {
arcAt(center, radius: radius, startAngle: 0, endAngle: twoPi)
}
}
![Page 84: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/84.jpg)
Adding a Circle Primitiveprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func circleAt(center: CGPoint, radius: CGFloat)
func arcAt(
center: CGPoint, radius: CGFloat,
startAngle: CGFloat, endAngle: CGFloat)
)
}
extension CGContext {
func circleAt(center: CGPoint, radius: CGFloat) {
arcAt(center, radius: radius, startAngle: 0, endAngle: twoPi)
}
}
![Page 85: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/85.jpg)
Protocol Extensionprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func circleAt(center: CGPoint, radius: CGFloat)
func arcAt(
center: CGPoint, radius: CGFloat,
startAngle: CGFloat, endAngle: CGFloat)
)
}
extension Renderer {
func circleAt(center: CGPoint, radius: CGFloat) {
arcAt(center, radius: radius, startAngle: 0, endAngle: twoPi)
}
}
New!
![Page 86: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/86.jpg)
Protocol Extensionprotocol Renderer {
func moveTo(p: CGPoint)
func lineTo(p: CGPoint)
func circleAt(center: CGPoint, radius: CGFloat)
func arcAt(
center: CGPoint, radius: CGFloat,
startAngle: CGFloat, endAngle: CGFloat)
)
}
extension Renderer {
func circleAt(center: CGPoint, radius: CGFloat) {
arcAt(center, radius: radius, startAngle: 0, endAngle: twoPi)
}
}
Shared Implementation
![Page 87: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/87.jpg)
Protocol Extensionextension Renderer {
func circleAt(center: CGPoint, radius: CGFloat) { ... }
func rectagleAt(edges: CGRect) { ... }
}
extension TestRenderer: Renderer {
func circleAt(center: CGPoint, radius: CGFloat) { ... }
func rectagleAt(edges: CGRect) { ... }
}
![Page 88: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/88.jpg)
Protocol Extensionextension Renderer {
func circleAt(center: CGPoint, radius: CGFloat) { ... }
func rectagleAt(edges: CGRect) { ... }
}
extension TestRenderer: Renderer {
func circleAt(center: CGPoint, radius: CGFloat) { ... }
func rectagleAt(edges: CGRect) { ... }
}
let r = TestRenderer()
r.circleAt(origin, radius: 1)
r.rectangleAt(edges)
![Page 89: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/89.jpg)
Protocol Extensionextension Renderer {
func circleAt(center: CGPoint, radius: CGFloat) { ... }
func rectagleAt(edges: CGRect) { ... }
}
extension TestRenderer: Renderer {
func circleAt(center: CGPoint, radius: CGFloat) { ... }
func rectagleAt(edges: CGRect) { ... }
}
let r = TestRenderer()
r.circleAt(origin, radius: 1)
r.rectangleAt(edges)
![Page 90: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/90.jpg)
Protocol Extensioncustomization pointextension Renderer {
func circleAt(center: CGPoint, radius: CGFloat) { ... }
func rectagleAt(edges: CGRect) { ... }
}
extension TestRenderer: Renderer {
func circleAt(center: CGPoint, radius: CGFloat) { ... }
func rectagleAt(edges: CGRect) { ... }
}
let r: Renderer = TestRenderer()
r.circleAt(origin, radius: 1)
r.rectangleAt(edges)
![Page 91: Protocol-Oriented Programming in Swift](https://reader038.vdocument.in/reader038/viewer/2022110109/586f96e21a28abcc238b4903/html5/thumbnails/91.jpg)
91
Questions