Skip to content

Instantly share code, notes, and snippets.

@thilo11
Created September 18, 2015 16:19
Show Gist options
  • Save thilo11/b8a0cf19f0afd2e113b7 to your computer and use it in GitHub Desktop.
Save thilo11/b8a0cf19f0afd2e113b7 to your computer and use it in GitHub Desktop.
The Xcode 7 playground for the Swift Meetup "Protocol-Oriented Programming in Swift" http://www.meetup.com/de/Swift-Meetup-Hamburg/events/224604913/
import XCPlayground
import Foundation
// in Xcode 7 use Editor/Show Rendered Markup to display the formatted comments
//: # First things first: The Protocols
//: It is good Swift practice to start with your protocols
//: Instead of a common base classes we define protocols
protocol Hardware {
var name: String {get}
var vendor: String {get}
func fullName () -> String
}
protocol ProgrammingLanguage {
var name:String {get}
var inventedIn:Int {get}
var inventors:[String] {get}
func numberOfInventors () -> Int
}
//: A cross cutting concern. We want to use loggers everywhere
protocol Logger {
func log(message:String) -> ()
}
//: A protocol with a 'Self' requirement.
protocol History {
func isInfluencedBy(other: Self) -> Bool
}
func >(lhs: ProgrammingLanguage, rhs: ProgrammingLanguage) -> Bool {
return lhs.inventedIn > rhs.inventedIn
}
func ==(lhs: ProgrammingLanguage, rhs: ProgrammingLanguage) -> Bool {
return lhs.inventedIn == rhs.inventedIn
}
//: # Protocol Extensions
//: Let's implement some default behaviour
extension ProgrammingLanguage {
func numberOfInventors () -> Int {
return inventors.count
}
}
//: Cool! We can access self. Compare to Java 8 Virtual Extension Methods
extension Logger {
func log(message:String) -> (){
print ("log msg: \(self.dynamicType): \(message)")
}
}
//: Even cooler: Declare conditions on the type
extension Logger where Self: ProgrammingLanguage {
func prettyLog(message:String) -> (){
print ("nice log msg: \(NSDate()) \(self.dynamicType): \(message)")
}
}
//: # Finally our structs
//: No (mutable) classes any more. We use structs (Value Types)
struct ComputerHardware: Hardware, Logger {
var name: String
var vendor: String
func fullName () -> String {
log("only simple logging allowed here")
return "\(vendor): \(name)"
}
}
//: No inheritance tree, we only 'mixin' the stuff we need
struct OoLanguage: ProgrammingLanguage, Logger {
let name:String
let inventors:[String]
let inventedIn: Int
let hasMultipleInheritance:Bool
}
struct FunctionalLanguage: ProgrammingLanguage, History, Logger {
let name: String
let inventors: [String]
let inventedIn: Int
let hasHighOrderFunctions: Bool
let hasImmutableCollections: Bool
func isInfluencedBy(other: FunctionalLanguage) -> Bool {
return self.inventedIn > other.inventedIn
}
func isCool() -> Bool {
prettyLog("fancy logging here")
return hasHighOrderFunctions && hasImmutableCollections
}
}
// doesn't work
//func doSomething(languages:[History]) -> [History]{
// return []
//}
// works using Generic Type, Self Requirement!
func doSomething<T:History>(languages:[T]) -> [T]{
return [languages.first!]
}
//: # Our Objects
let lispMachine = ComputerHardware(name: "3070", vendor: "Symbolics")
let clojure = FunctionalLanguage(name: "Clojure", inventors: ["Rich Hickey"], inventedIn: 2007, hasHighOrderFunctions: true, hasImmutableCollections: true)
let erlang = FunctionalLanguage(name: "Erlang", inventors: ["Joe Armstrong, Robert Virding, Mike Williams"], inventedIn: 1986, hasHighOrderFunctions: true, hasImmutableCollections: true)
let smalltalk = OoLanguage(name:"Smalltalk", inventors:["Alan Kay", "Dan Ingalls", "Adele Goldberg"], inventedIn: 1971, hasMultipleInheritance: false)
//: Does the extension work?
smalltalk.numberOfInventors()
clojure.numberOfInventors()
//: Does our logger work?
lispMachine.fullName() // simple logger
clojure.isCool() // fancy logger
//: protocols are types
let progLanguages:[ProgrammingLanguage] = [clojure, erlang, smalltalk]
let progLangNames = progLanguages.map({(lang) -> String in return lang.name})
progLangNames
clojure.isInfluencedBy(erlang)
progLanguages.sort(>)
doSomething([erlang, clojure])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment