Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Protocols. What's the Big Deal?

Protocols. What's the Big Deal?

Slides from my Swift London Talk about Protocols in Swift

Abizer Nasir

July 20, 2015
Tweet

More Decks by Abizer Nasir

Other Decks in Programming

Transcript

  1. - I conform to a protocol, so I honour this

    interface - Apply a common set of behaviours in a single inheritance system. UITableViewDataSource UIApplicationDelegate NSFetchedResultsSectionInfo
  2. struct Homer { ... var krusty: Krusty } Not much

    good having an embedded Krusty object.
  3. struct Homer { ... var krusty: KrustyDelegate } Whenever we

    want to do something Krusty like - we bounce out to the delegate But what about the other Franchisees?
  4. We could declare an array of Franchisees let franchisees: Array<T:

    KrustyDelegate> = [“Homer”, “Ned”, “Smithers”] But then we have to declare a delegate object for each. of them, or use some kind of factory method.
  5. FizzBuzz — If the number is a multiple of 3,

    print “Fizz” — If the number is a multiple of 5, print “Buzz” — If the number is a multiple of 3 and 5, print “FizzBuzz” — Otherwise, just print the number
  6. So for something like this: [1, 2, 3, 5, 10,

    15] We get: [“1”, “2”, “Buzz”, “Fizz”, “Fizz”, “FizzBuzz”]
  7. Extend Protocol to deal with this extension SequenceType where Generator.Element

    == Int { func fizzBuzz() -> [String] { return self.map { item -> String in switch (item % 3, item % 5) { case (0, 0): return “FizzBuzz” case (0, _): return “Buzz” case (_, 0): return “Fizz” default: return “\(item)” } } } }
  8. Provide configuration extension SequenceType where Generator.Element == Int { func

    fizzBuzz(options: [(Int, String)]) -> [String] { return self.map { item -> String in var output = “” for (divisor, description) in options { if item % divisor == 0 { output += description } } guard !output.isEmpty else { return “\(item)” } return output } } }
  9. Add a type constraint extension SequenceType where Generator.Element == Int,

    Generator.Element: CustomStringConvertible { func fizzBuzz(options: [(Int, String)]) -> [String] { return self.map { item -> String in var output = “” for (divisor, description) in options { if item % divisor == 0 { output += description } } guard !output.isEmpty else { return item.description } return output } } }
  10. Create a FizzBuzz Protocol protocol FizzBuzzable { func fizzBuzzValue() ->

    Int } extension Int: FizzBuzzable { func fizzBuzzValue() -> Int { return self } }
  11. Change the Type Constraint extension SequenceType where Generator.Element: FizzBuzzable, Generator.Element:

    CustomStringConvertible { func fizzBuzz(options: [(Int, String)]) -> [String] { return self.map { item -> String in var output = “” var value = item.fizzBuzzValue() for (divisor, description) in options { if value % divisor == 0 { output += description } } guard !output.isEmpty else { return value.description } return output } } }
  12. This works [1, 3, 5, 10, 15].fizzBuzz( [(3, “Fizz”), (5,

    “Buzz”)] ) // [“1”, “Fizz”, “Buzz”, “Buzz”, “FizzBuzz”]
  13. Extend other types to implement FizzBuzzable struct Shape { let

    sides: Int } extension Shape: FizzBuzzable { func fizzBuzzValue() -> Int { return sides } } extension Shape: CustomStringConvertible { var description: String { return sides.description } }
  14. And you can fizz buzz that as well [Shape(sides: 1),

    Shape(sides: 3), Shape(sides: 15)].fizzBuzz([(3, “Fizz”), (5, “Buzz”)]) // [“1”, “Fizz”, “FizzBuzz”] The mechanics of doing the actual FizzBuzz has been removed from the configuration of the FizzBuzz.
  15. data TrafficLight = Red | Yellow | Green deriving (Eq,

    Ord, Show) let r = Red let g = Green r == g # False r < g # True r # Red