protocol-oriented programming in swift

92
1

Upload: globallogic-ukraine

Post on 16-Apr-2017

533 views

Category:

Software


1 download

TRANSCRIPT

Page 1: Protocol-Oriented Programming in Swift

1

Page 2: Protocol-Oriented Programming in Swift

2

Protocol-oriented programming in SwiftRostyslav KobyzskyiSoftware Engineer16th Nov, 2016

Page 3: Protocol-Oriented Programming in Swift

3

1. Classes and problems2. Start with Protocol3. Using Protocols4. Examples5. Questions

Agenda

Page 4: Protocol-Oriented Programming in Swift

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

Why Protocols?

Page 6: Protocol-Oriented Programming in Swift

Classes• Encapsulation• Access Control• Abstraction• Namespace• Expressive Syntax• Extensibility

Page 7: Protocol-Oriented Programming in Swift

Classes• Encapsulation• Access Control• Abstraction• Namespace• Expressive Syntax• Extensibility

Page 8: Protocol-Oriented Programming in Swift

1. Implicit Sharing

A

B

Data

Page 9: Protocol-Oriented Programming in Swift

1. Implicit Sharing

A

B

Data

Page 10: Protocol-Oriented Programming in Swift

1. Implicit Sharing

A

B

Data

Page 11: Protocol-Oriented Programming in Swift

1. Implicit Sharing

A

B

Data

Page 12: Protocol-Oriented Programming in Swift

1. Implicit Sharing

A

B

Ponies

Page 13: Protocol-Oriented Programming in Swift

1. Implicit Sharing

B

Ponies

Page 14: Protocol-Oriented Programming in Swift

1. Implicit Sharing

B

Ponies

$@#$%?

Page 15: Protocol-Oriented Programming in Swift

1. Implicit Sharing• Defensive Copy• Inefficiency• Race Condition• Locks• More Inefficiency• Deadlock• Complexity• Bugs!

Page 16: Protocol-Oriented Programming in Swift

Values don’t Share.

That’s a good thingClasses? They overshare…

Page 17: Protocol-Oriented Programming in Swift

2. Inheritance

SubclassStoredProperties

Superclass

Page 18: Protocol-Oriented Programming in Swift

2. InheritanceOne superclass

SubclassStoredProperties

Superclass

Page 19: Protocol-Oriented Programming in Swift

Instance

2. InheritanceOne superclass

Single Inheritance

SubclassStoredProperties

Superclass

Page 20: Protocol-Oriented Programming in Swift

Instance

2. InheritanceOne superclass

Single Inheritance

Super class may have Stored Properties

SubclassStoredProperties

SuperclassStoredProperties

Page 21: Protocol-Oriented Programming in Swift

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

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

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

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

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

3. Lost Type Relationships

class Ordered {

func precedes(other: Ordered) -> Bool { }

}

Page 27: Protocol-Oriented Programming in Swift

3. Lost Type Relationships

class Ordered {

func precedes(other: Ordered) -> Bool

}

{ fatalError(“implement me!”) }

Page 28: Protocol-Oriented Programming in Swift

3. Lost Type Relationships

class Ordered {

func precedes(other: Ordered) -> Bool

}

{ fatalError(“implement me!”) } X

Page 29: Protocol-Oriented Programming in Swift

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

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

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

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

`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

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

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

Swift is Protocol-Oriented

Programming Language

Page 37: Protocol-Oriented Programming in Swift

Start with a Protocol

Page 38: Protocol-Oriented Programming in Swift

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Drawableprotocol Drawable {

func draw(randerer: Renderer)

}

Page 60: Protocol-Oriented Programming in Swift

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

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

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

Test It!var circle = Circle(

center: CGPoint(x: 187.5, y: 333.5),

radius: 93.75

)

Page 64: Protocol-Oriented Programming in Swift

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

91

Questions

Page 92: Protocol-Oriented Programming in Swift

92

Thank you

RostyslavSoftware [email protected]+38-093-254-3392