Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams...

261
© 2015 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple. Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408

Transcript of Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams...

Page 1: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

© 2015 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.

Protocol-Oriented Programming in Swift

Dave Abrahams Professor of Blowing-Your-Mind

Developer Tools #WWDC15

Session 408

Page 2: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Meet CrustyDon’t call him “Jerome”

Page 3: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t
Page 4: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Classes Are Awesome

Page 5: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

• Encapsulation

Classes Are Awesome

Page 6: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

• Encapsulation

• Access Control

Classes Are Awesome

Page 7: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

• Encapsulation

• Access Control

• Abstraction

Classes Are Awesome

Page 8: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

• Encapsulation

• Access Control

• Abstraction

• Namespace

Classes Are Awesome

Page 9: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

• Encapsulation

• Access Control

• Abstraction

• Namespace

• Expressive Syntax

Classes Are Awesome

Page 10: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

• Encapsulation

• Access Control

• Abstraction

• Namespace

• Expressive Syntax

• Extensibility

Classes Are Awesome

Page 11: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

• Encapsulation

• Access Control

• Abstraction

• Namespace

• Expressive Syntax

• Extensibility

Classes Are Awesome

Page 12: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Classes Are Awesome

•Encapsulation

• Access Control

• Abstraction

• Namespace

• Expressive Syntax

• Extensibility

Classes

Page 13: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Classes Are Awesome

•Encapsulation

• Access Control

• Abstraction

• Namespace

• Expressive Syntax

• Extensibility

ClassesClassesClassesTypes

I can do all

that with structs

Page 14: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Classes Are Awesome

•Encapsulation

• Access Control

• Abstraction

• Namespace

• Expressive Syntax

• Extensibility

ClassesClassesClassesTypes

I can do all

that with structs

and enums.

Page 15: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Classes Are AwesomeInheritance Hierarchies

UIDocument

UIManagedDocument

NSObject

UIResponder

UIApplication UIView

UIBarItem

UITabBarItemUIBarButtonItem

Page 16: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

NSObject

UIBarItem

UITabBarItemUIBarButtonItem

Classes Are AwesomeCustomization points and reuse

UIDocument

UIManagedDocument

Page 17: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Classes Are AwesomeCustomization points and reuse

UIDocumentsaveToURL(_:forSaveOperation:completionHandler:)

UIManagedDocument

Page 18: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Classes Are AwesomeCustomization points and reuse

UIDocumentsaveToURL(_:forSaveOperation:completionHandler:)

UIManagedDocument

Page 19: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Classes Are AwesomeCustomization points and reuse

UIDocumentsaveToURL(_:forSaveOperation:completionHandler:)

contentsForType(_)

UIManagedDocument

Page 20: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Classes Are AwesomeCustomization points and reuse

UIDocumentsaveToURL(_:forSaveOperation:completionHandler:)

contentsForType(_)

UIManagedDocumentcontentsForType(_)

Page 21: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Classes Are AwesomeCustomization points and reuse

UIDocumentsaveToURL(_:forSaveOperation:completionHandler:)

contentsForType(_) UIManagedDocumentcontentsForType(_)

Page 22: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

The Three BeefsCrusty's litany of complaints

Page 23: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit Sharing

B

DataA

Page 24: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit Sharing

B

Data

A

Page 25: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit Sharing

B

Data

A

Page 26: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit Sharing

B

Data

A

Page 27: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit Sharing

B

Data

A

Page 28: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit Sharing

B

Data

A

Page 29: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit Sharing

B

DataPonies

A

Page 30: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit Sharing

B

Ponies

Page 31: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit Sharing

B

Ponies

?!@##?

Page 32: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit SharingThe sad story

Page 33: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit SharingThe sad story

Defensive Copying

Page 34: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit SharingThe sad story

Defensive CopyingInefficiency

Page 35: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit SharingThe sad story

Defensive CopyingInefficiencyRace Conditions

Page 36: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit SharingThe sad story

Defensive CopyingInefficiencyRace ConditionsLocks

Page 37: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit SharingThe sad story

Defensive CopyingInefficiencyRace ConditionsLocksMore Inefficiency

Page 38: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit SharingThe sad story

Defensive CopyingInefficiencyRace ConditionsLocksMore InefficiencyDeadlock

Page 39: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit SharingThe sad story

Defensive CopyingInefficiencyRace ConditionsLocksMore InefficiencyDeadlockComplexity

Page 40: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

1. Implicit SharingThe sad story

Defensive CopyingInefficiencyRace ConditionsLocksMore InefficiencyDeadlockComplexityBugs!

Page 41: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

This is not news.

@property(copy), coding conventions…

Page 42: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

NOTEIt is not safe to modify a mutable collection while enumerating through it. Some enumerators may currently allow enumeration of a collection that is modified, but this behavior is not guaranteed to be supported in the future.

One effect of implicit sharing on Cocoa

1. Implicit Sharing

Page 43: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

NOTEIt is not safe to modify a mutable collection while enumerating through it. Some enumerators may currently allow enumeration of a collection that is modified, but this behavior is not guaranteed to be supported in the future.

One effect of implicit sharing on Cocoa

Cocoa Collections Only

1. Implicit Sharing

Page 44: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Values Don't Share.(That's a good thing).

Classes? They overshare.

Building Better Apps with Value Types in Swift Mission Friday 2:30PM

Page 45: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

2. Inheritance All Up In Your Business

SubclassStored Properties

Page 46: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

2. Inheritance All Up In Your Business

One superclass — choose well!

Subclass

Superclass

Stored Properties

Page 47: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

2. Inheritance All Up In Your Business

One superclass — choose well!Single Inheritance weight gain

Subclass

Superclass

Stored Properties

Page 48: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

2. Inheritance All Up In Your Business

One superclass — choose well!Single Inheritance weight gainNo retroactive modeling

Subclass

Superclass

Stored Properties

Page 49: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

2. Inheritance All Up In Your Business

One superclass — choose well!Single Inheritance weight gainNo retroactive modelingSuperclass may have stored properties

Instance

Subclass

SuperclassStored Properties

Stored Properties

Page 50: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

2. Inheritance All Up In Your Business

One superclass — choose well!Single Inheritance weight gainNo retroactive modelingSuperclass may have stored properties• You must accept them

Instance

Subclass

SuperclassStored Properties

Stored Properties

Page 51: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

2. Inheritance All Up In Your Business

One superclass — choose well!Single Inheritance weight gainNo retroactive modelingSuperclass may have stored properties• You must accept them• Initialization burden

Instance

Subclass

SuperclassStored Properties

Stored Properties

Page 52: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

2. Inheritance All Up In Your Business

One superclass — choose well!Single Inheritance weight gainNo retroactive modelingSuperclass may have stored properties• You must accept them• Initialization burden• Don’t break superclass invariants!

Instance

Subclass

SuperclassStored Properties

Stored Properties

Page 53: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

2. Inheritance All Up In Your Business

One superclass — choose well!Single Inheritance weight gainNo retroactive modelingSuperclass may have stored properties• You must accept them• Initialization burden• Don’t break superclass invariants!

Know what/how to override (and when not to)

Instance

Subclass

SuperclassStored Properties

Stored Properties

Page 54: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

This is not news.

More and more, we promote delegation.

Page 55: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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 56: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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 57: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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 58: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

Page 59: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

Page 60: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

Page 61: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

Page 62: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return value < other.value } }

Page 63: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return value < other.value } }

Page 64: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return value < other.value } }

Page 65: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return value < other.value } } 'Ordered' does not have a member

named 'value'

Page 66: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return value < other.value } } 'Ordered' does not have a member

named 'value'

Page 67: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Label : Ordered { var text: String = "" ... }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return value < other.value } } 'Ordered' does not have a member

named 'value'

Page 68: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Label : Ordered { var text: String = "" ... }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return value < other.value } }

Page 69: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Label : Ordered { var text: String = "" ... }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return value < (other as! Number).value } }

Page 70: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

3. Lost Type Relationships

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Label : Ordered { var text: String = "" ... }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return value < (other as! Number).value } }

Page 71: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

as! ASubclass

A sign that a type relationship was lostUsually due to using classes for abstraction

Page 72: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

A Better Abstraction Mechanism

Supports value types (and classes)Supports static type relationships (and dynamic dispatch)Non-monolithicSupports retroactive modelingDoesn’t impose instance data on modelsDoesn’t impose initialization burdens on modelsMakes clear what to implement

Page 73: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Swift Is a Protocol-Oriented Programming Language

Page 74: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Start with a Protocol

Your first stop for new abstractions

Page 75: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return self.value < (other as! Number).value } }

Page 76: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

class Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return self.value < (other as! Number).value } }

Page 77: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

protocol Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return self.value < (other as! Number).value } }

Page 78: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

protocol Ordered { func precedes(other: Ordered) -> Bool { fatalError("implement me!") } }

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return self.value < (other as! Number).value } }

error: protocol methods may not have bodies

Page 79: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

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

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return self.value < (other as! Number).value } }

Page 80: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

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

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return self.value < (other as! Number).value } }

error: method does not override any method from its superclass

Page 81: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

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

class Number : Ordered { var value: Double = 0 override func precedes(other: Ordered) -> Bool { return self.value < (other as! Number).value } }

Page 82: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

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

struct Number : Ordered { var value: Double = 0 func precedes(other: Ordered) -> Bool { return self.value < (other as! Number).value } }

Page 83: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

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

struct Number : Ordered { var value: Double = 0 func precedes(other: Ordered) -> Bool { return self.value < (other as! Number).value } }

Page 84: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

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

struct Number : Ordered { var value: Double = 0 func precedes(other: Ordered) -> Bool { return self.value < (other as! Number).value } }

Page 85: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

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

struct Number : Ordered { var value: Double = 0 func precedes(other: Number) -> Bool { return self.value < other.value } }

Page 86: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

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

struct Number : Ordered { var value: Double = 0 func precedes(other: Number) -> Bool { return self.value < other.value } }

protocol requires function 'precedes' with type '(Ordered) -> Bool'candidate has non-matching type '(Number) -> Bool'

Page 87: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

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

struct Number : Ordered { var value: Double = 0 func precedes(other: Number) -> Bool { return self.value < other.value } }

Page 88: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

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

struct Number : Ordered { var value: Double = 0 func precedes(other: Number) -> Bool { return self.value < other.value } }

Page 89: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

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

struct Number : Ordered { var value: Double = 0 func precedes(other: Number) -> Bool { return self.value < other.value } }

“Self” requirement

Page 90: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Starting Over with Protocols

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

struct Number : Ordered { var value: Double = 0 func precedes(other: Number) -> Bool { return self.value < other.value } }

Page 91: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Using Our Protocol

func binarySearch(sortedKeys: [Ordered], forKey k: Ordered) -> Int { var lo = 0 var 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 92: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Using Our Protocol

func binarySearch(sortedKeys: [Ordered], forKey k: Ordered) -> Int { var lo = 0 var 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 93: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Using Our Protocol

func binarySearch(sortedKeys: [Ordered], forKey k: Ordered) -> Int { var lo = 0 var 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 it has Self or associated type requirements

Page 94: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Using Our Protocol

func binarySearch(sortedKeys: [Ordered], forKey k: Ordered) -> Int { var lo = 0 var 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 95: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Using Our Protocol

func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { var lo = 0 var 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 96: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Using Our Protocol

func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { var lo = 0 var 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 97: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Two Worlds of Protocols

Without Self Requirement With Self Requirement

func precedes(other: Ordered) -> Bool func precedes(other: Self) -> Bool

Page 98: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Two Worlds of Protocols

Without Self Requirement With Self Requirement

func precedes(other: Ordered) -> Bool func precedes(other: Self) -> Bool

Usable as a typefunc sort(inout a: [Ordered])

Only usable as a generic constraintfunc sort<T : Ordered>(inout a: [T])

Page 99: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Two Worlds of Protocols

Without Self Requirement With Self Requirement

func precedes(other: Ordered) -> Bool func precedes(other: Self) -> Bool

Usable as a typefunc sort(inout a: [Ordered])

Only usable as a generic constraintfunc sort<T : Ordered>(inout a: [T])

Think “heterogeneous” Think “homogeneous”

Page 100: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Two Worlds of Protocols

Without Self Requirement With Self Requirement

func precedes(other: Ordered) -> Bool func precedes(other: Self) -> Bool

Usable as a typefunc sort(inout a: [Ordered])

Only usable as a generic constraintfunc sort<T : Ordered>(inout a: [T])

Think “heterogeneous” Think “homogeneous”

Every model must deal with all others Models are free from interaction

Page 101: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Two Worlds of Protocols

Without Self Requirement With Self Requirement

func precedes(other: Ordered) -> Bool func precedes(other: Self) -> Bool

Usable as a typefunc sort(inout a: [Ordered])

Only usable as a generic constraintfunc sort<T : Ordered>(inout a: [T])

Think “heterogeneous” Think “homogeneous”

Every model must deal with all others Models are free from interaction

Dynamic dispatch Static dispatch

Page 102: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Two Worlds of Protocols

Without Self Requirement With Self Requirement

func precedes(other: Ordered) -> Bool func precedes(other: Self) -> Bool

Usable as a typefunc sort(inout a: [Ordered])

Only usable as a generic constraintfunc sort<T : Ordered>(inout a: [T])

Think “heterogeneous” Think “homogeneous”

Every model must deal with all others Models are free from interaction

Dynamic dispatch Static dispatch

Less optimizable More optimizable

Page 103: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

A Challenge for Crusty

Prove it!

Page 104: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

A Primitive “Renderer”

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, startAngle: CGFloat, endAngle: CGFloat) { print("arcAt(\(center), radius: \(radius)," + " startAngle: \(startAngle), endAngle: \(endAngle))") } }

Page 105: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Drawable

protocol Drawable { func draw(renderer: Renderer) }

Page 106: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Polygon

protocol Drawable { func draw(renderer: Renderer) }

struct Polygon : Drawable { func draw(renderer: Renderer) { renderer.moveTo(corners.last!) for p in corners { renderer.lineTo(p) } } var corners: [CGPoint] = [] }

Page 107: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Polygon

protocol Drawable { func draw(renderer: Renderer) }

struct Polygon : Drawable { func draw(renderer: Renderer) { renderer.moveTo(corners.last!) for p in corners { renderer.lineTo(p) } } var corners: [CGPoint] = [] }

Page 108: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Polygon

protocol Drawable { func draw(renderer: Renderer) }

struct Polygon : Drawable { func draw(renderer: Renderer) { renderer.moveTo(corners.last!) for p in corners { renderer.lineTo(p) } } var corners: [CGPoint] = [] }

Page 109: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Circle

protocol Drawable { func draw(renderer: Renderer) }

struct Circle : Drawable { func draw(renderer: Renderer) { renderer.arcAt(center, radius: radius, startAngle: 0.0, endAngle: twoPi) } var center: CGPoint var radius: CGFloat }

Page 110: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Circle

protocol Drawable { func draw(renderer: Renderer) }

struct Circle : Drawable { func draw(renderer: Renderer) { renderer.arcAt(center, radius: radius, startAngle: 0.0, endAngle: twoPi) } var center: CGPoint var radius: CGFloat }

Page 111: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Circle

protocol Drawable { func draw(renderer: Renderer) }

struct Circle : Drawable { func draw(renderer: Renderer) { renderer.arcAt(center, radius: radius, startAngle: 0.0, endAngle: twoPi) } var center: CGPoint var radius: CGFloat }

Page 112: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Diagram

struct Diagram : Drawable { func draw(renderer: Renderer) { for f in elements { f.draw(renderer) } } var elements: [Drawable] = [] }

Page 113: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Diagram

struct Diagram : Drawable { func draw(renderer: Renderer) { for f in elements { f.draw(renderer) } } var elements: [Drawable] = [] }

Page 114: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Diagram

struct Diagram : Drawable { func draw(renderer: Renderer) { for f in elements { f.draw(renderer) } } var elements: [Drawable] = [] }

Page 115: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Diagram

struct Diagram : Drawable { func draw(renderer: Renderer) { for f in elements { f.draw(renderer) } } var elements: [Drawable] = [] }

Page 116: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Test It!

var circle = Circle(center:CGPoint(x: 187.5, y: 333.5),radius: 93.75)

Page 117: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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 118: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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 119: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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 120: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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())

$ ./test

Page 121: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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())

$ ./testarcAt((187.5, 333.5),radius: 93.75, startAngle: 0.0,endAngle: 6.28318530717959)

moveTo(106.310118395209, 286.625)lineTo(187.5, 427.25)lineTo(268.689881604791, 286.625)lineTo(106.310118395209, 286.625)$

Page 122: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Renderer as a Protocol

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, startAngle: CGFloat, endAngle: CGFloat) { print("arcAt(\(center), radius: \(radius)," + " startAngle: \(startAngle), endAngle: \(endAngle))") }}

Page 123: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Renderer as a Protocol

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, startAngle: 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,

Page 124: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Renderer as a Protocol

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, startAngle: 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,

Page 125: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Renderer as a Protocol

protocol 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, startAngle: 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,

Page 126: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Renderer as a Protocol

protocol 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, startAngle: 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,

Page 127: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Renderer as a Protocol

protocol 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, startAngle: 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,

Page 128: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: 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,

Renderer as a Protocol

Page 129: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: 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,

Renderer as a Protocol

Page 130: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: 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,

Renderer as a Protocol

Page 131: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: 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,

Renderer as a Protocol

Page 132: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: 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,

Renderer as a Protocol

Page 133: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Rendering with CoreGraphicsRetroactive modeling

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) }

Page 134: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Rendering with CoreGraphicsRetroactive modeling

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) }

Page 135: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Rendering with CoreGraphicsRetroactive modeling

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) }

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) }

Page 136: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Rendering with CoreGraphicsRetroactive modeling

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) }

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) }

Page 137: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Rendering with CoreGraphicsRetroactive modeling

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) }

extension CGContext : Renderer { func moveTo(p: CGPoint) { } func lineTo(p: CGPoint) { } func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) { } }

Page 138: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Rendering with CoreGraphicsRetroactive modeling

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) }

extension CGContext : Renderer { func moveTo(p: CGPoint) { } func lineTo(p: CGPoint) { } func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) { } }

Page 139: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Rendering with CoreGraphicsRetroactive modeling

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) }

extension CGContext : Renderer { func moveTo(p: CGPoint) { } func lineTo(p: CGPoint) { } func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) { } }

Page 140: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Rendering with CoreGraphicsRetroactive modeling

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint) func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) }

extension CGContext : Renderer { func moveTo(p: CGPoint) { } func lineTo(p: CGPoint) { } func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) { } }

Page 141: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Rendering with CoreGraphicsRetroactive modeling

extension CGContext : Renderer { func moveTo(p: CGPoint) {

} func lineTo(p: CGPoint) {

} func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) {

} }

Page 142: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

CGContextMoveToPoint(self, position.x, position.y)

CGContextAddLineToPoint(self, position.x, position.y)

let arc = CGPathCreateMutable()CGPathAddArc(arc, nil, c.x, c.y, radius, startAngle, endAngle, true)CGContextAddPath(self, arc)

Rendering with CoreGraphicsRetroactive modeling

extension CGContext : Renderer { func moveTo(p: CGPoint) {

} func lineTo(p: CGPoint) {

} func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) {

} }

Page 143: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Crustacean: The Playgroundhttps://developer.apple.com/sample-code/wwdc/2015/

Page 144: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Nested Diagram

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 145: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Nested Diagram

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.elements.append(diagram)

Page 146: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Nested Diagram

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.elements.append(diagram)

Building Better Apps with Value Types in Swift Mission Friday 2:30PM

Page 147: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Building Better Apps with Value Types in Swift Mission Friday 2:30PM

Nested Diagram

var circle = Circle(center: CGPoint(x: 187.5, y: 333.5

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.elements.append(diagram)

$ ./test arcAt((187.5, 333.5), radius: 93.75, startAngle: 0.0, endAngle: 6.28318530717959) moveTo(106.310118395209, 286.625) lineTo(187.5, 427.25) lineTo(268.689881604791, 286.625) lineTo(106.310118395209, 286.625) arcAt((187.5, 333.5), radius: 93.75, startAngle: 0.0, endAngle: 6.28318530717959) moveTo(106.310118395209, 286.625) lineTo(187.5, 427.25) lineTo(268.689881604791, 286.625) lineTo(106.310118395209, 286.625) $

Page 148: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Building Better Apps with Value Types in Swift Mission Friday 2:30PM

Nested Diagram

var circle = Circle(center: CGPoint(x: 187.5, y: 333.5

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.elements.append(diagram)

$ ./test arcAt((187.5, 333.5), radius: 93.75, startAngle: 0.0, endAngle: 6.28318530717959) moveTo(106.310118395209, 286.625) lineTo(187.5, 427.25) lineTo(268.689881604791, 286.625) lineTo(106.310118395209, 286.625) arcAt((187.5, 333.5), radius: 93.75, startAngle: 0.0, endAngle: 6.28318530717959) moveTo(106.310118395209, 286.625) lineTo(187.5, 427.25) lineTo(268.689881604791, 286.625) lineTo(106.310118395209, 286.625) $

Page 149: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Building Better Apps with Value Types in Swift Mission Friday 2:30PM

Nested Diagram

var circle = Circle(center: CGPoint(x: 187.5, y: 333.5

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.elements.append(diagram)

$ ./test arcAt((187.5, 333.5), radius: 93.75, startAngle: 0.0, endAngle: 6.28318530717959) moveTo(106.310118395209, 286.625) lineTo(187.5, 427.25) lineTo(268.689881604791, 286.625) lineTo(106.310118395209, 286.625) arcAt((187.5, 333.5), radius: 93.75, startAngle: 0.0, endAngle: 6.28318530717959) moveTo(106.310118395209, 286.625) lineTo(187.5, 427.25) lineTo(268.689881604791, 286.625) lineTo(106.310118395209, 286.625) $

Page 150: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Building Better Apps with Value Types in Swift Mission Friday 2:30PM

Nested Diagram

var circle = Circle(center: CGPoint(x: 187.5, y: 333.5

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.elements.append(diagram)

$ ./test arcAt((187.5, 333.5), radius: 93.75, startAngle: 0.0, endAngle: 6.28318530717959) moveTo(106.310118395209, 286.625) lineTo(187.5, 427.25) lineTo(268.689881604791, 286.625) lineTo(106.310118395209, 286.625) arcAt((187.5, 333.5), radius: 93.75, startAngle: 0.0, endAngle: 6.28318530717959) moveTo(106.310118395209, 286.625) lineTo(187.5, 427.25) lineTo(268.689881604791, 286.625) lineTo(106.310118395209, 286.625) $

Page 151: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Nested Diagram

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.elements.append(diagram)

Page 152: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Nested Diagram

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.elements.append(diagram)

Page 153: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Nested Diagram

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.elements.append( Scaled(scale: 0.3, subject: diagram))

Page 154: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Nested Diagram

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.elements.append( Scaled(scale: 0.3, subject: diagram))

Page 155: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Nested Diagram

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.elements.append( Scaled(scale: 0.3, subject: diagram))

Page 156: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Protocols and Generics for TestabilitySo much better than mocks

Disciplined decoupling is a beautiful thing.

Page 157: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bubble

struct Bubble : Drawable { func draw(r: Renderer) { r.arcAt(center, radius: radius, startAngle: 0, endAngle: twoPi) r.arcAt(highlightCenter, radius: highlightRadius,

startAngle: 0, endAngle: twoPi) } }

Page 158: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bubble

struct Bubble : Drawable { func draw(r: Renderer) { r.arcAt(center, radius: 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: radius, startAngle: 0.0, endAngle: twoPi) } }

Page 159: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bubble

struct Bubble : Drawable { func draw(r: Renderer) { r.circleAt(center, radius: radius) r.circleAt(highlightCenter, radius: highlightRadius) } }

struct Circle : Drawable { func draw(r: Renderer) { r.circleAt(center, radius: radius) } }

Page 160: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Adding a Circle Primitive

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint)

func arcAt( center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) }

Page 161: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Adding a Circle Primitive

protocol Renderer { func moveTo(p: CGPoint) func lineTo(p: CGPoint)

func arcAt( center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) }

Page 162: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Adding a Circle Primitive

protocol 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 163: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Adding a Circle Primitive

protocol 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 164: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Implementing the Requirement

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

New requirement

Page 165: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Implementing the Requirement… Again!

protocol 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 166: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Implementing the Requirement… Again!

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

Duplicate implementation

Page 167: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Implementing the Requirement… Again!

protocol 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 168: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Protocol Extensions

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

Page 169: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Protocol Extensions

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

Page 170: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Protocol Extensions

protocol 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 171: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Protocol Extensions

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

Page 172: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Protocol ExtensionsRequirements create customization points

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

Page 173: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Protocol ExtensionsRequirements create customization points

protocol 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) { ... }

}

Page 174: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Protocol ExtensionsRequirements create customization points

protocol 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) { ... }

}

Page 175: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Protocol ExtensionsRequirements create customization points

protocol 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) { ... } func rectangleAt(edges: CGRect) { ... } }

Page 176: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Protocol ExtensionsRequirements create customization points

protocol 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) { ... } func rectangleAt(edges: CGRect) { ... } }

Page 177: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

Protocol ExtensionsRequirements create customization points

Page 178: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

Protocol ExtensionsRequirements create customization points

Page 179: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

Protocol ExtensionsRequirements create customization points

Page 180: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

Protocol ExtensionsRequirements create customization points

Page 181: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

let r = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Page 182: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

let r = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Page 183: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

let r = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Page 184: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

let r = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Page 185: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

let r = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Page 186: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

let r = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Page 187: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

let r: Renderer = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Page 188: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

let r: Renderer = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Page 189: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

let r: Renderer = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Page 190: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

let r: Renderer = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Provides the requirement

Page 191: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

let r: Renderer = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Page 192: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... } func rectangleAt(edges: CGRect) { ... } }

let r: Renderer = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Page 193: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

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) { ... } func rectangleAt(edges: CGRect) { ... } }

extension TestRenderer : Renderer { func circleAt(center: CGPoint, radius: CGFloat) { ... }

}

let r: Renderer = TestRenderer() r.circleAt(origin, radius: 1); r.rectangleAt(edges);

Protocol ExtensionsRequirements create customization points

Page 194: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksScenes from the standard library and beyond

Page 195: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksConstrained extensions

extension CollectionType { public func indexOf(element: Generator.Element) -> Index? { for i in self.indices { if self[i] == element { return i } } return nil } }

Page 196: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksConstrained extensions

extension CollectionType { public func indexOf(element: Generator.Element) -> Index? { for i in self.indices { if self[i] == element { return i } } return nil } }

binary operator '==' cannot be applied to two Generator.Element operands

Page 197: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksConstrained extensions

extension CollectionType { public func indexOf(element: Generator.Element) -> Index? { for i in self.indices { if self[i] == element { return i } } return nil } }

binary operator '==' cannot be applied to two Generator.Element operands

Page 198: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksConstrained extensions

extension CollectionType where Generator.Element : Equatable { public func indexOf(element: Generator.Element) -> Index? { for i in self.indices { if self[i] == element { return i } } return nil } }

Page 199: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

Page 200: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

let position = binarySearch([2, 3, 5, 7], forKey: 5)

Page 201: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

let position = binarySearch([2, 3, 5, 7], forKey: 5)

cannot invoke 'binarySearch' with an argument list of type '([Int], forKey: Int)'

Page 202: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Int : Ordered { func precedes(other: Int) -> Bool { return self < other } }

let position = binarySearch([2, 3, 5, 7], forKey: 5)

Page 203: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Int : Ordered { func precedes(other: Int) -> Bool { return self < other } }

let position = binarySearch(["2", "3", "5", "7"], forKey: "5")

Page 204: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Int : Ordered { func precedes(other: Int) -> Bool { return self < other } }

let position = binarySearch(["2", "3", "5", "7"], forKey: "5")

cannot invoke 'binarySearch' with an argument list of type '([String], forKey: String)'

Page 205: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Int : Ordered { func precedes(other: Int) -> Bool { return self < other } } extension String : Ordered { func precedes(other: String) -> Bool { return self < other } }

let position = binarySearch(["2", "3", "5", "7"], forKey: "5")

Page 206: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Comparable { func precedes(other: Self) -> Bool { return self < other } } extension Int : Ordered {} extension String : Ordered {}

let position = binarySearch(["2", "3", "5", "7"], forKey: "5")

Page 207: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Comparable { func precedes(other: Self) -> Bool { return self < other } } extension Int : Ordered {} extension String : Ordered {} extension Double : Ordered {}

let position = binarySearch(["2", "3", "5", "7"], forKey: "5")

Page 208: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Comparable { func precedes(other: Self) -> Bool { return self < other } } extension Int : Ordered {} extension String : Ordered {}

let position = binarySearch(["2", "3", "5", "7"], forKey: "5")

Page 209: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Comparable { func precedes(other: Self) -> Bool { return self < other } } extension Int : Ordered {} extension String : Ordered {} let truth = 3.14.precedes(98.6) // Compiles

let position = binarySearch(["2", "3", "5", "7"], forKey: "5")

Page 210: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Comparable { func precedes(other: Self) -> Bool { return self < other } } extension Int : Ordered {} extension String : Ordered {} let truth = 3.14.precedes(98.6) // Compiles

let position = binarySearch([2.0, 3.0, 5.0, 7.0], forKey: 5.0)

Page 211: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Comparable { func precedes(other: Self) -> Bool { return self < other } } extension Int : Ordered {} extension String : Ordered {} let truth = 3.14.precedes(98.6) // Compiles

let position = binarySearch([2.0, 3.0, 5.0, 7.0], forKey: 5.0)

cannot invoke 'binarySearch' with an argument list of type '([Double], forKey: Double)'

Page 212: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Comparable { func precedes(other: Self) -> Bool { return self < other } } extension Int : Ordered {} extension String : Ordered {} let truth = 3.14.precedes(98.6) // Compiles

Page 213: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Ordered where Self : Comparable { func precedes(other: Self) -> Bool { return self < other } } extension Int : Ordered {} extension String : Ordered {} let truth = 3.14.precedes(98.6)

Page 214: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksRetroactive adaptation

protocol Ordered { func precedes(other: Self) -> Bool } func binarySearch<T : Ordered>(sortedKeys: [T], forKey k: T) -> Int { ... }

extension Ordered where Self : Comparable { func precedes(other: Self) -> Bool { return self < other } } extension Int : Ordered {} extension String : Ordered {} let truth = 3.14.precedes(98.6)

'Double' does not have a member named 'precedes'

Page 215: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksGeneric beautification

func binarySearch< C : CollectionType where C.Index == RandomAccessIndexType, C.Generator.Element : Ordered >(sortedKeys: C, forKey k: C.Generator.Element) -> Int {

...

}

let pos = binarySearch([2, 3, 5, 7, 11, 13, 17], 5)forKey:

Page 216: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksGeneric beautification

CollectionType where Index == RandomAccessIndexType, Generator.Element : Ordered {

func binarySearch(forKey: Generator.Element) -> Int { ... }

}

let pos = [2, 3, 5, 7, 11, 13, 17].binarySearch(5)

extension 2

Page 217: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksGeneric beautification

CollectionType where Index == RandomAccessIndexType, Generator.Element : Ordered {

func binarySearch(forKey: Generator.Element) -> Int { ... }

}

let pos = [2, 3, 5, 7, 11, 13, 17].binarySearch(5)

extension 2

Page 218: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksGeneric beautification

CollectionType where Index == RandomAccessIndexType, Generator.Element : Ordered {

func binarySearch(forKey: Generator.Element) -> Int { ... }

}

let pos = [2, 3, 5, 7, 11, 13, 17].binarySearch(5)

extension

Page 219: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksGeneric beautification

CollectionType where Index == RandomAccessIndexType, Generator.Element : Ordered {

func binarySearch(forKey: Generator.Element) -> Int { ... }

}

let pos = [2, 3, 5, 7, 11, 13, 17].binarySearch(5)

extension

Page 220: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksInterface generation

Page 221: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Protocol Extension TricksInterface generation

Page 222: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Make All Value Types Equatable

func == (lhs: Polygon, rhs: Polygon) -> Bool { return lhs.corners == rhs.corners } extension Polygon : Equatable {}

func == (lhs: Circle, rhs: Circle) -> Bool { return lhs.center == rhs.center && lhs.radius == rhs.radius } extension Circle : Equatable {}

Page 223: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Make All Value Types Equatable

func == (lhs: Polygon, rhs: Polygon) -> Bool { return lhs.corners == rhs.corners } extension Polygon : Equatable {}

func == (lhs: Circle, rhs: Circle) -> Bool { return lhs.center == rhs.center && lhs.radius == rhs.radius } extension Circle : Equatable {}

Building Better Apps with Value Types in Swift Mission Friday 2:30PM

Page 224: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Make All Value Types Equatable

struct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements == rhs.elements }

Page 225: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Make All Value Types Equatable

struct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements == rhs.elements }

binary operator '==' cannot be applied to two [Drawable] operands.

Page 226: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Make All Value Types Equatable

struct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements == rhs.elements }

Page 227: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Make All Value Types Equatable

struct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { $0 != $1 } }

Page 228: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Make All Value Types Equatable

struct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { $0 != $1 } }

binary operator '!=' cannot be applied to two Drawable operands.

Page 229: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Make All Value Types Equatable

struct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { $0 != $1 } }

Page 230: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Should Every Drawable Be Equatable?

struct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { $0 != $1 } }

protocol Drawable : Equatable { func draw() }

Page 231: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Should Every Drawable Be Equatable?

struct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { $0 != $1 } }

protocol Drawable : Equatable { func draw() }

protocol Equatable { func == (Self, Self) -> Bool }

Page 232: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Should Every Drawable Be Equatable?

struct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { $0 != $1 } }

protocol Drawable : Equatable { func draw() }

protocol Equatable { func == (Self, Self) -> Bool }

Page 233: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bridge-Building

struct Diagram : Drawable, Equatable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { !$0.isEqualTo($1) } }

protocol Drawable { func isEqualTo(other: Drawable) -> Bool func draw() }

Page 234: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bridge-Building

struct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { !$0.isEqualTo($1) } }

protocol Drawable { func isEqualTo(other: Drawable) -> Bool func draw() }

Page 235: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bridge-Buildingstruct Diagram : Drawable {func draw(renderer: Renderer) { ... }var elements: [Drawable] = []

}

func == (lhs: Diagram, rhs: Diagram) -> Bool {return lhs.elements.count == rhs.elements.count

&& !zip(lhs.elements, rhs.elements).contains { !$0.isEqualTo($1) }}protocol Drawable {func isEqualTo(other: Drawable) -> Boolfunc draw()

}

Page 236: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bridge-Buildingstruct Diagram : Drawable {func draw(renderer: Renderer) { ... }var elements: [Drawable] = []

}

func == (lhs: Diagram, rhs: Diagram) -> Bool {return lhs.elements.count == rhs.elements.count

&& !zip(lhs.elements, rhs.elements).contains { !$0.isEqualTo($1) }}protocol Drawable {func isEqualTo(other: Drawable) -> Boolfunc draw()

}extension Drawable where Self : Equatable {func isEqualTo(other: Drawable) -> Bool {if let o = other as? Self { return self == o }return false

}}

Page 237: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bridge-Buildingstruct Diagram : Drawable {func draw(renderer: Renderer) { ... }var elements: [Drawable] = []

}

func == (lhs: Diagram, rhs: Diagram) -> Bool {return lhs.elements.count == rhs.elements.count

&& !zip(lhs.elements, rhs.elements).contains { !$0.isEqualTo($1) }}protocol Drawable {func isEqualTo(other: Drawable) -> Boolfunc draw()

}extension Drawable where Self : Equatable {func isEqualTo(other: Drawable) -> Bool {if let o = other as? Self { return self == o }return false

}}

Page 238: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bridge-Buildingstruct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { !$0.isEqualTo($1) } } protocol Drawable { func isEqualTo(other: Drawable) -> Bool func draw() } extension Drawable where Self : Equatable { func isEqualTo(other: Drawable) -> Bool { if let o = other as? Self { return self == o } return false } }

Page 239: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bridge-Buildingstruct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { !$0.isEqualTo($1) } } protocol Drawable { func isEqualTo(other: Drawable) -> Bool func draw() } extension Drawable where Self : Equatable { func isEqualTo(other: Drawable) -> Bool { if let o = other as? Self { return self == o } return false } }

Page 240: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bridge-Buildingstruct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { !$0.isEqualTo($1) } } protocol Drawable { func isEqualTo(other: Drawable) -> Bool func draw() } extension Drawable where Self : Equatable { func isEqualTo(other: Drawable) -> Bool { if let o = other as? Self { return self == o } return false } }

Page 241: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bridge-Buildingstruct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { !$0.isEqualTo($1) } } protocol Drawable { func isEqualTo(other: Drawable) -> Bool func draw() } extension Drawable where Self : Equatable { func isEqualTo(other: Drawable) -> Bool { if let o = other as? Self { return self == o } return false } }

Page 242: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Bridge-Buildingstruct Diagram : Drawable { func draw(renderer: Renderer) { ... } var elements: [Drawable] = [] }

func == (lhs: Diagram, rhs: Diagram) -> Bool { return lhs.elements.count == rhs.elements.count && !zip(lhs.elements, rhs.elements).contains { !$0.isEqualTo($1) } } protocol Drawable { func isEqualTo(other: Drawable) -> Bool func draw() } extension Drawable where Self : Equatable { func isEqualTo(other: Drawable) -> Bool { if let o = other as? Self { return self == o } return false } }

Page 243: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

When to Use ClassesThey do have their place…

You want implicit sharing when

Page 244: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

When to Use ClassesThey do have their place…

You want implicit sharing when• Copying or comparing instances doesn't make sense (e.g., Window)

Page 245: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

When to Use ClassesThey do have their place…

You want implicit sharing when• Copying or comparing instances doesn't make sense (e.g., Window)• Instance lifetime is tied to external effects (e.g., TemporaryFile)

Page 246: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

When to Use ClassesThey do have their place…

You want implicit sharing when• Copying or comparing instances doesn't make sense (e.g., Window)• Instance lifetime is tied to external effects (e.g., TemporaryFile)• Instances are just “sinks”—write-only conduits to external state (e.g., CGContext)

Page 247: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

When to Use ClassesThey do have their place…

You want implicit sharing when• Copying or comparing instances doesn't make sense (e.g., Window)• Instance lifetime is tied to external effects (e.g., TemporaryFile)• Instances are just “sinks”—write-only conduits to external state (e.g., CGContext)

final class StringRenderer : Renderer { var result: String ... }

Page 248: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

When to Use ClassesThey do have their place…

You want implicit sharing when• Copying or comparing instances doesn't make sense (e.g., Window)• Instance lifetime is tied to external effects (e.g., TemporaryFile)• Instances are just “sinks”—write-only conduits to external state (e.g., CGContext)

final class StringRenderer : Renderer { var result: String ... }

Still a protocol!

Page 249: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

When to Use ClassesThey do have their place…

Page 250: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

When to Use ClassesThey do have their place…

Don't fight the system• If a framework expects you to subclass, or to pass an object, do!

Page 251: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

When to Use ClassesThey do have their place…

Don't fight the system• If a framework expects you to subclass, or to pass an object, do!

On the other hand, be circumspect • Nothing in software should grow too large• When factoring something out of a class, consider a non-class

Page 252: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Summary

Page 253: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Summary

Protocols > Superclasses

Page 254: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Summary

Protocols > SuperclassesProtocol extensions = magic (almost)

Page 255: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Summary

Protocols > SuperclassesProtocol extensions = magic (almost)Go see the value types talk on Friday!

Page 256: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Summary

Protocols > SuperclassesProtocol extensions = magic (almost)Go see the value types talk on Friday!Eat your vegetables

Page 257: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Summary

Protocols > SuperclassesProtocol extensions = magic (almost)Go see the value types talk on Friday!Eat your vegetablesBe like Crusty…

Page 258: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t
Page 259: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

More Information

Swift Language Documentationhttp://developer.apple.com/swift

Apple Developer Forumshttp://developer.apple.com/forums

Stefan LesserSwift [email protected]

Page 260: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t

Related Sessions

Building Better Apps with Value Types in Swift Mission Friday 2:30PM

Page 261: Protocol-Oriented Programming in Swift...Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind Developer Tools #WWDC15 Session 408 Meet Crusty Don’t