-
Notifications
You must be signed in to change notification settings - Fork 3
Protocol Oriented Programming
Ben Guo edited this page Jun 18, 2015
·
7 revisions
(WWDC15-408)
Both types and classes provide:
- Encapsulation
- Access Control
- Abstraction
- Namespace
- Expressive Syntax
- Customization points and reuse
Classes are bad:
- Implicit sharing
- Class inheritance is too intrusive
- single inheritance weight gain
- no retroactive modeling (need superclass first)
- superclass may have stored properties (initialization burden)
- don't break superclass invariants!
- know what/how to override (and when not to)
- Lost type relationships
"Swift is a protocol-oriented programming language"
"Start with a protocol"
- Protocol with self requirement means homogeneous, static dispatch
- Protocols and generics are better than mocks for testing
- mocks are inherently fragile and don't play well with static type system
protocol Renderer {
func moveTo(p: _)
func circleAt(center: _, radius: _) { ... }
}
extension Renderer {
func circleAt(center: _, radius: _) { ... }
func rectangleAt(edges: _) { ... }
}
extension TestRenderer : Renderer {
func circleAt(center: _, radius: _) { ... }
func rectangleAt(edges: _) { ... }
}
let r: Renderer = TestRenderer()
r.circleAt(origin, radius: 1)
// TestRenderer->circleAt
// Because circleAt is a requirement, our model has the privilege of customizing it
r.rectangleAt(edges)
// Renderer->rectangleAt
// rectangelAt isn't a requirement. TestRenderer's implementation shadows the protocol implementation, so protocol implementation is called.
- Constrained extensions
extension CollectionType where Generator.Element : Equatable {
extension Ordered where Self : Comparable
- Nicer looking generics
extension CollectionType where Index == RandomAccessIndexType,
Generator.Element : Ordered {
func binarySearch(forKey: Generator.Element) -> Int {
}
}
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)
Don't fight the system
- When factoring something out a class, consider a value type