• Ebdb3b6516bdc3b4c57dfedebd607159?s=80&d=mm

    Changes from Seoh

    Seoh - over 5 years ago (Jun 07, 2014, 11:02 AM)
    23. 프로토콜 초벌 완료
  • Changes have been accepted Merged
      Looks like something's not quite right here.. We've been notified of the issue, and will get back to you soon.
      chapter23
      # 23 프로토콜 (Protocols)
      > Translator : 이름 (메일주소)

      A protocol defines a blueprint of methods, properties, and other requirements that suit a
      particular task or piece of functionality. The protocol doesn’t actually provide an
      implementation for any of these requirements—it only describes what an implementation
      will look like. The protocol can then be adopted by a class, structure, or enumeration to
      provide an actual implementation of those requirements. Any type that satisfies the
      requirements of a protocol is said to conform to that protocol.
      프로토콜은 특정 작업이나 기능에 부합하는 메소드, 속성, 그리고 다른 요구사항들에 대한 청사진과 같습니다. 프로토콜에는 이런 요구사항들에 대한 어떤 구현도 포함하지 않고, 다만 구현된 모습이 어떨지 윤곽만 드러납니다. 그러면 클래스, 구조체나 열거형에서 프로토콜을 따라 요구사항들을 실제로 구현하게 됩니다. 프로토콜의 요구사항을 만족하는 형(`type`)이라면 그 프로토콜에 들어맞다(conform)라고 하죠.

      Protocols can require that conforming types have specific instance properties, instance
      methods, type methods, operators, and subscripts.
      Protocol Syntax
      You define protocols in a very similar way to classes, structures, and enumerations:
      protocol SomeProtocol {
      // protocol definition goes here
      }
      Custom types state that they adopt a particular protocol by placing the protocol’s name
      after the type’s name, separated by a colon, as part of their definition. Multiple protocols
      can be listed, and are separated by commas:
      struct SomeStructure: FirstProtocol, AnotherProtocol {
      // structure definition goes here
      }
      If a class has a superclass, list the superclass name before any protocols it adopts,
      followed by a comma:
      class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {
      // class definition goes here
      }
      Property Requirements
      A protocol can require any conforming type to provide an instance property or type
      property with a particular name and type. The protocol doesn’t specify whether the
      property should be a stored property or a computed property—it only specifies the
      required property name and type. The protocol also specifies whether each property must
      be gettable or gettable and settable.
      If a protocol requires a property to be gettable and settable, that property requirement
      cannot be fulfilled by a constant stored property or a read-only computed property. If the
      protocol only requires a property to be gettable, the requirement can be satisfied by any
      kind of property, and it is valid for it also to be settable if this is useful for your own code.
      Property requirements are always declared as variable properties, prefixed with the var
      keyword. Gettable and settable properties are indicated by writing { get set } after their
      type declaration, and gettable properties are indicated by writing { get }.
      protocol SomeProtocol {
      var mustBeSettable: Int { get set }
      var doesNotNeedToBeSettable: Int { get }
      }
      Always prefix type property requirements with the class keyword when you define them in
      a protocol. This is true even though type property requirements are prefixed with the static
      keyword when implemented by a structure or enumeration:
      protocol AnotherProtocol {
      class var someTypeProperty: Int { get set }
      }
      Here’s an example of a protocol with a single instance property requirement:
      protocol FullyNamed {
      var fullName: String { get }
      }
      The FullyNamed protocol defines any kind of thing that has a fully-qualified name. It doesn’t
      specify what kind of thing it must be—it only specifies that the thing must be able to
      provide a full name for itself. It specifies this requirement by stating that any FullyNamed
      type must have a gettable instance property called fullName, which is of type String.
      Here’s an example of a simple structure that adopts and conforms to the FullyNamed
      protocol:
      struct Person: FullyNamed {
      var fullName: String
      }
      let john = Person(fullName: "John Appleseed")
      // john.fullName is "John Appleseed"
      This example defines a structure called Person, which represents a specific named person.
      It states that it adopts the FullyNamed protocol as part of the first line of its definition.
      Each instance of Person has a single stored property called fullName, which is of type String.
      This matches the single requirement of the FullyNamed protocol, and means that Person has
      correctly conformed to the protocol. (Swift reports an error at compile-time if a protocol
      requirement is not fulfilled.)
      Here’s a more complex class, which also adopts and conforms to the FullyNamed protocol:
      class Starship: FullyNamed {
      var prefix: String?
      var name: String
      init(name: String, prefix: String? = nil) {
      self.name = name
      self.prefix = prefix
      }
      var fullName: String {
      return (prefix ? prefix! + " " : "") + name
      ncc1701 = Starship(name: "Enterprise", prefix: "USS")
      ncc1701.fullName is "USS Enterprise"
      This class implements the fullName property requirement as a computed read-only property
      for a starship. Each Starship class instance stores a mandatory name and an optional prefix.
      The fullName property uses the prefix value if it exists, and prepends it to the beginning of
      name to create a full name for the starship.
      Method Requirements
      Protocols can require specific instance methods and type methods to be implemented by
      conforming types. These methods are written as part of the protocol’s definition in exactly
      the same way as for normal instance and type methods, but without curly braces or a
      method body. Variadic parameters are allowed, subject to the same rules as for normal
      methods.
      N O T E
      Protocols use the same syntax as normal methods, but are not allowed to specify default values for method
      parameters.
      As with type property requirements, you always prefix type method requirements with the
      class keyword when they are defined in a protocol. This is true even though type method
      requirements are prefixed with the static keyword when implemented by a structure or
      enumeration:
      protocol SomeProtocol {
      class func someTypeMethod()
      }
      The following example defines a protocol with a single instance method requirement:
      protocol RandomNumberGenerator {
      func random() -> Double
      }
      This protocol, RandomNumberGenerator, requires any conforming type to have an instance
      method called random, which returns a Double value whenever it is called. (Although it is not
      specified as part of the protocol, it is assumed that this value will be a number between
      0.0 and 1.0 inclusive.)
      The RandomNumberGenerator protocol does not make any assumptions about how each random
      number will be generated—it simply requires the generator to provide a standard way to
      generate a new random number.
      Here’s an implementation of a class that adopts and conforms to the RandomNumberGenerator
      protocol. This class implements a pseudorandom number generator algorithm known as a
      linear congruential generator:
      class LinearCongruentialGenerator: RandomNumberGenerator {
      var lastRandom = 42.0
      let m = 139968.0
      let a = 3877.0
      let c = 29573.0
      func random() -> Double {
      lastRandom = ((lastRandom * a + c) % m)
      return lastRandom / m
      }
      generator = LinearCongruentialGenerator()
      ("Here's a random number: \(generator.random())")
      prints "Here's a random number: 0.37464991998171"
      ("And another one: \(generator.random())")
      prints "And another one: 0.729023776863283"
      Mutating Method Requirements
      It is sometimes necessary for a method to modify (or mutate) the instance it belongs to.
      For instance methods on value types (that is, structures and enumerations) you place the
      mutating keyword before a method’s func keyword to indicate that the method is allowed to
      modify the instance it belongs to and/or any properties of that instance. This process is
      described in Modifying Value Types from Within Instance Methods.
      If you define a protocol instance method requirement that is intended to mutate
      instances of any type that adopts the protocol, mark the method with the mutating keyword
      as part of the protocol’s definition. This enables structures and enumerations to adopt the
      protocol and satisfy that method requirement.
      N O T E
      If you mark a protocol instance method requirement as mutating, you do not need to write the mutating
      keyword when writing an implementation of that method for a class. The mutating keyword is only used by
      structures and enumerations.
      The example below defines a protocol called Togglable, which defines a single instance
      method requirement called toggle. As its name suggests, the toggle method is intended to
      toggle or invert the state of any conforming type, typically by modifying a property of that
      type.
      The toggle method is marked with the mutating keyword as part of the Togglable protocol
      definition, to indicate that the method is expected to mutate the state of a conforming
      instance when it is called:
      protocol Togglable {
      mutating func toggle()
      }
      If you implement the Togglable protocol for a structure or enumeration, that structure or
      enumeration can conform to the protocol by providing an implementation of the toggle
      method that is also marked as mutating.
      The example below defines an enumeration called OnOffSwitch. This enumeration toggles
      between two states, indicated by the enumeration cases On and Off. The enumeration’s
      toggle implementation is marked as mutating, to match the Togglable protocol’s requirements:
      enum OnOffSwitch: Togglable {
      case Off, On
      mutating func toggle() {
      switch self {
      case Off:
      self = On
      case On:
      self = Off
      }
      lightSwitch = OnOffSwitch.Off
      lightSwitch.toggle()
      lightSwitch is now equal to .On
      Protocols as Types
      Protocols do not actually implement any functionality themselves. Nonetheless, any
      protocol you create will become a fully-fledged type for use in your code.
      Because it is a type, you can use a protocol in many places where other types are
      allowed, including:
      N O T E
      Because protocols are types, begin their names with a capital letter (such as FullyNamed and
      RandomNumberGenerator) to match the names of other types in Swift (such as Int, String, and Double).
      Here’s an example of a protocol used as a type:
      class Dice {
      let sides: Int
      let generator: RandomNumberGenerator
      init(sides: Int, generator: RandomNumberGenerator) {
      self.sides = sides
      self.generator = generator
      }
      func roll() -> Int {
      return Int(generator.random() * Double(sides)) + 1
      This example defines a new class called Dice, which represents an n-sided dice for use in a
      board game. Dice instances have an integer property called sides, which represents how
      many sides they have, and a property called generator, which provides a random number
      generator from which to create dice roll values.
      As a parameter type or return type in a function, method, or initializer
      As the type of a constant, variable, or property
      As the type of items in an array, dictionary, or other container
      The generator property is of type RandomNumberGenerator. Therefore, you can set it to an
      instance of any type that adopts the RandomNumberGenerator protocol. Nothing else is required
      of the instance you assign to this property, except that the instance must adopt the
      RandomNumberGenerator protocol.
      Dice also has an initializer, to set up its initial state. This initializer has a parameter called
      generator, which is also of type RandomNumberGenerator. You can pass a value of any conforming
      type in to this parameter when initializing a new Dice instance.
      Dice provides one instance method, roll, which returns an integer value between 1 and the
      number of sides on the dice. This method calls the generator’s random method to create a
      new random number between 0.0 and 1.0, and uses this random number to create a dice
      roll value within the correct range. Because generator is known to adopt RandomNumberGenerator,
      it is guaranteed to have a random method to call.
      Here’s how the Dice class can be used to create a six-sided dice with a
      LinearCongruentialGenerator instance as its random number generator:
      var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
      for _ in 1...5 {
      println("Random dice roll is \(d6.roll())")
      }
      // Random dice roll is 3
      // Random dice roll is 5
      // Random dice roll is 4
      // Random dice roll is 5
      // Random dice roll is 4
      Delegation
      Delegation is a design pattern that enables a class or structure to hand off (or delegate)
      some of its responsibilities to an instance of another type. This design pattern is
      implemented by defining a protocol that encapsulates the delegated responsibilities, such
      that a conforming type (known as a delegate) is guaranteed to provide the functionality
      that has been delegated. Delegation can be used to respond to a particular action, or to
      retrieve data from an external source without needing to know the underlying type of that
      source.
      The example below defines two protocols for use with dice-based board games:
      protocol DiceGame {
      var dice: Dice { get }
      func play()
      }
      protocol DiceGameDelegate {
      func gameDidStart(game: DiceGame)
      func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
      func gameDidEnd(game: DiceGame)
      }
      The DiceGame protocol is a protocol that can be adopted by any game that involves dice.
      The DiceGameDelegate protocol can be adopted by any type to track the progress of a DiceGame.
      Here’s a version of the Snakes and Ladders game originally introduced in Control Flow.
      This version is adapted to use a Dice instance for its dice-rolls; to adopt the DiceGame
      protocol; and to notify a DiceGameDelegate about its progress:
      class SnakesAndLadders: DiceGame {
      let finalSquare = 25
      let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
      var square = 0
      var board: Int[]
      init() {
      board = Int[](count: finalSquare + 1, repeatedValue: 0)
      board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
      board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
      var delegate: DiceGameDelegate?
      func play() {
      square = 0
      delegate?.gameDidStart(self)
      gameLoop: while square != finalSquare {
      let diceRoll = dice.roll()
      delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
      switch square + diceRoll {
      case finalSquare:
      break gameLoop
      case let newSquare where newSquare > finalSquare:
      continue gameLoop
      default:
      square += diceRoll
      square += board[square]
      }
      }
      delegate?.gameDidEnd(self)
      For a description of the Snakes and Ladders gameplay, see the Break section of the
      Control Flow chapter.
      This version of the game is wrapped up as a class called SnakesAndLadders, which adopts the
      DiceGame protocol. It provides a gettable dice property and a play method in order to conform
      to the protocol. (The dice property is declared as a constant property because it does not
      need to change after initialization, and the protocol only requires that it is gettable.)
      The Snakes and Ladders game board setup takes place within the class’s init() initializer.
      All game logic is moved into the protocol’s play method, which uses the protocol’s required
      dice property to provide its dice roll values.
      Note that the delegate property is defined as an optional DiceGameDelegate, because a delegate
      isn’t required in order to play the game. Because it is of an optional type, the delegate
      property is automatically set to an initial value of nil. Thereafter, the game instantiator has
      the option to set the property to a suitable delegate.
      DiceGameDelegate provides three methods for tracking the progress of a game. These three
      methods have been incorporated into the game logic within the play method above, and
      are called when a new game starts, a new turn begins, or the game ends.
      Because the delegate property is an optional DiceGameDelegate, the play method uses optional
      chaining each time it calls a method on the delegate. If the delegate property is nil, these
      delegate calls fail gracefully and without error. If the delegate property is non-nil, the
      delegate methods are called, and are passed the SnakesAndLadders instance as a parameter.
      This next example shows a class called DiceGameTracker, which adopts the DiceGameDelegate
      protocol:
      class DiceGameTracker: DiceGameDelegate {
      var numberOfTurns = 0
      func gameDidStart(game: DiceGame) {
      numberOfTurns = 0
      if game is SnakesAndLadders {
      println("Started a new game of Snakes and Ladders")
      }
      println("The game is using a \(game.dice.sides)-sided dice")
      }
      func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
      ++numberOfTurns
      println("Rolled a \(diceRoll)")
      func gameDidEnd(game: DiceGame) {
      println("The game lasted for \(numberOfTurns) turns")
      DiceGameTracker implements all three methods required by DiceGameDelegate. It uses these
      methods to keep track of the number of turns a game has taken. It resets a numberOfTurns
      property to zero when the game starts; increments it each time a new turn begins; and
      prints out the total number of turns once the game has ended.
      The implementation of gameDidStart shown above uses the game parameter to print some
      introductory information about the game that is about to be played. The game parameter
      has a type of DiceGame, not SnakesAndLadders, and so gameDidStart can access and use only
      methods and properties that are implemented as part of the DiceGame protocol. However,
      the method is still able to use type casting to query the type of the underlying instance.
      In this example, it checks whether game is actually an instance of SnakesAndLadders behind the
      scenes, and prints an appropriate message if so.
      gameDidStart also accesses the dice property of the passed game parameter. Because game is
      known to conform to the DiceGame protocol, it is guaranteed to have a dice property, and so
      the gameDidStart method is able to access and print the dice’s sides property, regardless of
      what kind of game is being played.
      Here’s how DiceGameTracker looks in action:
      let tracker = DiceGameTracker()
      let game = SnakesAndLadders()
      game.delegate = tracker
      game.play()
      // Started a new game of Snakes and Ladders
      // The game is using a 6-sided dice
      // Rolled a 3
      // Rolled a 5
      // Rolled a 4
      Rolled a 5
      The game lasted for 4 turns
      Adding Protocol Conformance with an Extension
      You can extend an existing type to adopt and conform to a new protocol, even if you do
      not have access to the source code for the existing type. Extensions can add new
      properties, methods, and subscripts to an existing type, and are therefore able to add any
      requirements that a protocol may demand. For more about extensions, see Extensions.
      N O T E
      Existing instances of a type automatically adopt and conform to a protocol when that conformance is added to
      the instance’s type in an extension.
      For example, this protocol, called TextRepresentable, can be implemented by any type that
      has a way to be represented as text. This might be a description of itself, or a text
      version of its current state:
      protocol TextRepresentable {
      func asText() -> String
      }
      The Dice class from earlier can be extended to adopt and conform to TextRepresentable:
      extension Dice: TextRepresentable {
      func asText() -> String {
      return "A \(sides)-sided dice"
      }
      }
      This extension adopts the new protocol in exactly the same way as if Dice had provided it
      in its original implementation. The protocol name is provided after the type name,
      separated by a colon, and an implementation of all requirements of the protocol is
      provided within the extension’s curly braces.
      Any Dice instance can now be treated as TextRepresentable:
      let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
      println(d12.asText())
      // prints "A 12-sided dice"
      Similarly, the SnakesAndLadders game class can be extended to adopt and conform to the
      TextRepresentable protocol:
      extension SnakesAndLadders: TextRepresentable {
      func asText() -> String {
      return "A game of Snakes and Ladders with \(finalSquare) squares"
      }
      }
      println(game.asText())
      // prints "A game of Snakes and Ladders with 25 squares"
      Declaring Protocol Adoption with an Extension
      If a type already conforms to all of the requirements of a protocol, but has not yet stated
      that it adopts that protocol, you can make it adopt the protocol with an empty extension:
      struct Hamster {
      var name: String
      func asText() -> String {
      return "A hamster named \(name)"
      }
      }
      extension Hamster: TextRepresentable {}
      Instances of Hamster can now be used wherever TextRepresentable is the required type:
      let simonTheHamster = Hamster(name: "Simon")
      let somethingTextRepresentable: TextRepresentable = simonTheHamster
      println(somethingTextRepresentable.asText())
      // prints "A hamster named Simon"
      N O T E
      Types do not automatically adopt a protocol just by satisfying its requirements. They must always explicitly
      declare their adoption of the protocol.
      Collections of Protocol Types
      A protocol can be used as the type to be stored in a collection such as an array or a
      dictionary, as mentioned in Protocols as Types. This example creates an array of
      TextRepresentable things:
      let things: TextRepresentable[] = [game, d12, simonTheHamster]
      It is now possible to iterate over the items in the array, and print each item’s textual
      representation:
      for thing in things {
      println(thing.asText())
      }
      // A game of Snakes and Ladders with 25 squares
      // A 12-sided dice
      // A hamster named Simon
      Note that the thing constant is of type TextRepresentable. It is not of type Dice, or DiceGame, or
      Hamster, even if the actual instance behind the scenes is of one of those types.
      Nonetheless, because it is of type TextRepresentable, and anything that is TextRepresentable is
      known to have an asText method, it is safe to call thing.asText each time through the loop.
      Protocol Inheritance
      A protocol can inherit one or more other protocols and can add further requirements on
      top of the requirements it inherits. The syntax for protocol inheritance is similar to the
      syntax for class inheritance, but with the option to list multiple inherited protocols,
      separated by commas:
      protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
      // protocol definition goes here
      }
      Here’s an example of a protocol that inherits the TextRepresentable protocol from above:
      protocol PrettyTextRepresentable: TextRepresentable {
      func asPrettyText() -> String
      }
      This example defines a new protocol, PrettyTextRepresentable, which inherits from
      TextRepresentable. Anything that adopts PrettyTextRepresentable must satisfy all of the
      requirements enforced by TextRepresentable, plus the additional requirements enforced by
      PrettyTextRepresentable. In this example, PrettyTextRepresentable adds a single requirement to
      provide an instance method called asPrettyText that returns a String.
      The SnakesAndLadders class can be extended to adopt and conform to PrettyTextRepresentable:
      extension SnakesAndLadders: PrettyTextRepresentable {
      func asPrettyText() -> String {
      var output = asText() + ":¶
      "
      for index in 1...finalSquare {
      switch board[index] {
      case let ladder where ladder > 0:
      output += "▲ "
      case let snake where snake < 0:
      output += "▼ "
      default:
      output += "○ "
      }
      }
      return output
      This extension states that it adopts the PrettyTextRepresentable protocol and provides an
      implementation of the asPrettyText method for the SnakesAndLadders type. Anything that is
      PrettyTextRepresentable must also be TextRepresentable, and so the asPrettyText implementation
      starts by calling the asText method from the TextRepresentable protocol to begin an output
      string. It appends a colon and a line break, and uses this as the start of its pretty text
      representation. It then iterates through the array of board squares, and appends an emoji
      representation for each square:
      The method implementation can now be used to print a pretty text description of any
      SnakesAndLadders instance:
      println(game.asPrettyText())
      // A game of Snakes and Ladders with 25 squares:
      // ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○
      If the square’s value is greater than 0, it is the base of a ladder, and is
      represented by ▲.
      If the square’s value is less than 0, it is the head of a snake, and is represented by
      ▼.
      Otherwise, the square’s value is 0, and it is a “free” square, represented by ○.
      Protocol Composition
      It can be useful to require a type to conform to multiple protocols at once. You can
      combine multiple protocols into a single requirement with a protocol composition.
      Protocol compositions have the form protocol. You can list as many
      protocols within the pair of angle brackets (<>) as you need, separated by commas.
      Here’s an example that combines two protocols called Named and Aged into a single
      protocol composition requirement on a function parameter:
      protocol Named {
      var name: String { get }
      }
      protocol Aged {
      var age: Int { get }
      }
      struct Person: Named, Aged {
      var name: String
      var age: Int
      wishHappyBirthday(celebrator: protocol) {
      println("Happy birthday \(celebrator.name) - you're \(celebrator.age)!")
      birthdayPerson = Person(name: "Malcolm", age: 21)
      wishHappyBirthday(birthdayPerson)
      prints "Happy birthday Malcolm - you're 21!"
      This example defines a protocol called Named, with a single requirement for a gettable String
      property called name. It also defines a protocol called Aged, with a single requirement for a
      gettable Int property called age. Both of these protocols are adopted by a structure called
      Person.
      The example also defines a function called wishHappyBirthday, which takes a single parameter
      called celebrator. The type of this parameter is protocol, which means “any type
      that conforms to both the Named and Aged protocols.” It doesn’t matter what specific type is
      passed to the function, as long as it conforms to both of the required protocols.
      The example then creates a new Person instance called birthdayPerson and passes this new
      instance to the wishHappyBirthday function. Because Person conforms to both protocols, this is a
      valid call, and the wishHappyBirthday function is able to print its birthday greeting.
      N O T E
      Protocol compositions do not define a new, permanent protocol type. Rather, they define a temporary local
      protocol that has the combined requirements of all protocols in the composition.
      Checking for Protocol Conformance
      You can use the is and as operators described in Type Casting to check for protocol
      conformance, and to cast to a specific protocol. Checking for and casting to a protocol
      follows exactly the same syntax as checking for and casting to a type:
      This example defines a protocol called HasArea, with a single property requirement of a
      gettable Double property called area:
      @objc protocol HasArea {
      var area: Double { get }
      }
      N O T E
      You can check for protocol conformance only if your protocol is marked with the @objc attribute, as seen for
      the HasArea protocol above. This attribute indicates that the protocol should be exposed to Objective-C code
      and is described in Using Swift with Cocoa and Objective-C. Even if you are not interoperating with Objective-C,
      you need to mark your protocols with the @objc attribute if you want to be able to check for protocol
      conformance.
      Note also that @objc protocols can be adopted only by classes, and not by structures or enumerations. If you
      mark your protocol as @objc in order to check for conformance, you will be able to apply that protocol only to
      class types.
      The is operator returns true if an instance conforms to a protocol and returns false if
      it does not.
      The as? version of the downcast operator returns an optional value of the
      protocol’s type, and this value is nil if the instance does not conform to that
      protocol.
      The as version of the downcast operator forces the downcast to the protocol type
      and triggers a runtime error if the downcast does not succeed.
      Here are two classes, Circle and Country, both of which conform to the HasArea protocol:
      class Circle: HasArea {
      let pi = 3.1415927
      var radius: Double
      var area: Double { return pi * radius * radius }
      init(radius: Double) { self.radius = radius }
      }
      class Country: HasArea {
      var area: Double
      init(area: Double) { self.area = area }
      The Circle class implements the area property requirement as a computed property, based
      on a stored radius property. The Country class implements the area requirement directly as a
      stored property. Both classes correctly conform to the HasArea protocol.
      Here’s a class called Animal, which does not conform to the HasArea protocol:
      class Animal {
      var legs: Int
      init(legs: Int) { self.legs = legs }
      }
      The Circle, Country and Animal classes do not have a shared base class. Nonetheless, they are
      all classes, and so instances of all three types can be used to initialize an array that
      stores values of type AnyObject:
      let objects: AnyObject[] = [
      Circle(radius: 2.0),
      Country(area: 243_610),
      Animal(legs: 4)
      ]
      The objects array is initialized with an array literal containing a Circle instance with a radius
      of 2 units; a Country instance initialized with the surface area of the United Kingdom in
      square kilometers; and an Animal instance with four legs.
      The objects array can now be iterated, and each object in the array can be checked to see
      if it conforms to the HasArea protocol:
      for object in objects {
      if let objectWithArea = object as? HasArea {
      println("Area is \(objectWithArea.area)")
      } else {
      println("Something that doesn't have an area")
      }
      }
      // Area is 12.5663708
      // Area is 243610.0
      Something that doesn't have an area
      Whenever an object in the array conforms to the HasArea protocol, the optional value
      returned by the as? operator is unwrapped with optional binding into a constant called
      objectWithArea. The objectWithArea constant is known to be of type HasArea, and so its area
      property can be accessed and printed in a type-safe way.
      Note that the underlying objects are not changed by the casting process. They continue
      to be a Circle, a Country and an Animal. However, at the point that they are stored in the
      objectWithArea constant, they are only known to be of type HasArea, and so only their area
      property can be accessed.
      Optional Protocol Requirements
      You can define optional requirements for protocols, These requirements do not have to
      be implemented by types that conform to the protocol. Optional requirements are
      prefixed by the @optional keyword as part of the protocol’s definition.
      An optional protocol requirement can be called with optional chaining, to account for the
      possibility that the requirement was not implemented by a type that conforms to the
      protocol. For information on optional chaining, see Optional Chaining.
      You check for an implementation of an optional requirement by writing a question mark
      after the name of the requirement when it is called, such as someOptionalMethod?(someArgument).
      Optional property requirements, and optional method requirements that return a value,
      will always return an optional value of the appropriate type when they are accessed or
      called, to reflect the fact that the optional requirement may not have been implemented.
      N O T E
      Optional protocol requirements can only be specified if your protocol is marked with the @objc attribute. Even if
      you are not interoperating with Objective-C, you need to mark your protocols with the @objc attribute if you
      want to specify optional requirements.
      Note also that @objc protocols can be adopted only by classes, and not by structures or enumerations. If you
      mark your protocol as @objc in order to specify optional requirements, you will only be able to apply that
      protocol to class types.
      The following example defines an integer-counting class called Counter, which uses an
      external data source to provide its increment amount. This data source is defined by the
      CounterDataSource protocol, which has two optional requirements:
      @objc protocol CounterDataSource {
      @optional func incrementForCount(count: Int) -> Int
      @optional var fixedIncrement: Int { get }
      }
      The CounterDataSource protocol defines an optional method requirement called incrementForCount
      and an optional property requirement called fixedIncrement. These requirements define two
      different ways for data sources to provide an appropriate increment amount for a Counter
      instance.
      N O T E
      Strictly speaking, you can write a custom class that conforms to CounterDataSource without implementing
      either protocol requirement. They are both optional, after all. Although technically allowed, this wouldn’t make
      for a very good data source.
      The Counter class, defined below, has an optional dataSource property of type CounterDataSource?:
      @objc class Counter {
      var count = 0
      var dataSource: CounterDataSource?
      func increment() {
      if let amount = dataSource?.incrementForCount?(count) {
      count += amount
      } else if let amount = dataSource?.fixedIncrement? {
      count += amount
      }
      The Counter class stores its current value in a variable property called count. The Counter class
      also defines a method called increment, which increments the count property every time the
      method is called.
      The increment method first tries to retrieve an increment amount by looking for an
      implementation of the incrementForCount method on its data source. The increment method uses
      optional chaining to try to call incrementForCount, and passes the current count value as the
      method’s single argument.
      Note two levels of optional chaining at play here. Firstly, it is possible that dataSource may
      be nil, and so dataSource has a question mark after its name to indicate that incrementForCount
      should only be called if dataSource is non-nil. Secondly, even if dataSource does exist, there is
      no guarantee that it implements incrementForCount, because it is an optional requirement.
      This is why incrementForCount is also written with a question mark after its name.
      Because the call to incrementForCount can fail for either of these two reasons, the call returns
      an optional Int value. This is true even though incrementForCount is defined as returning a nonoptional
      Int value in the definition of CounterDataSource.
      After calling incrementForCount, the optional Int that it returns is unwrapped into a constant
      called amount, using optional binding. If the optional Int does contain a value—that is, if the
      delegate and method both exist, and the method returned a value—the unwrapped amount
      is added onto the stored count property, and incrementation is complete.
      If it is not possible to retrieve a value from the incrementForCount method—either because
      dataSource is nil, or because the data source does not implement incrementForCount—then the
      increment method tries to retrieve a value from the data source’s fixedIncrement property
      instead. The fixedIncrement property is also an optional requirement, and so its name is also
      written using optional chaining with a question mark on the end, to indicate that the
      attempt to access the property’s value can fail. As before, the returned value is an
      optional Int value, even though fixedIncrement is defined as a non-optional Int property as
      part of the CounterDataSource protocol definition.
      Here’s a simple CounterDataSource implementation where the data source returns a constant
      value of 3 every time it is queried. It does this by implementing the optional fixedIncrement
      property requirement:
      class ThreeSource: CounterDataSource {
      let fixedIncrement = 3
      }
      You can use an instance of ThreeSource as the data source for a new Counter instance:
      var counter = Counter()
      counter.dataSource = ThreeSource()
      for _ in 1...4 {
      counter.increment()
      println(counter.count)
      }
      // 3
      // 6
      // 9
      The code above creates a new Counter instance; sets its data source to be a new ThreeSource
      instance; and calls the counter’s increment method four times. As expected, the counter’s
      count property increases by three each time increment is called.
      Here’s a more complex data source called TowardsZeroSource, which makes a Counter instance
      count up or down towards zero from its current count value:
      class TowardsZeroSource: CounterDataSource {
      func incrementForCount(count: Int) -> Int {
      if count == 0 {
      return 0
      } else if count < 0 {
      return 1
      } else {
      return -1
      }
      The TowardsZeroSource class implements the optional incrementForCount method from the
      CounterDataSource protocol and uses the count argument value to work out which direction to
      count in. If count is already zero, the method returns 0 to indicate that no further counting
      should take place.
      You can use an instance of TowardsZeroSource with the existing Counter instance to count from -
      4 to zero. Once the counter reaches zero, no more counting takes place:
      counter.count = -4
      counter.dataSource = TowardsZeroSource()
      for _ in 1...5 {
      counter.increment()
      println(counter.count)
      }
      // -3
      // -2
      // -1
      . 프로토콜

      *프로토콜*은 특정한 일이나 기능의 일부에 대한 메소드나 속성이나 다른 요구사항들의 전체적인 모습을 정의한다.
      실제로 이런 요구사항들의 구현을 제공하지는 않고, 그 구현이 어떻게 보일지에 대해 명시한다.
      이 요구사항들을 실제로 구현된 클래스, 구조체, 열거형 등에 그 프로토콜이 *적용*될 수 있다.
      프로토콜의 요구사항을 만족하면 어떤 타입이라도 그 프로토콜에 *일치한다(conform)*라고 말한다.


      프로토콜은 특정한 인스턴스 속성들, 인스턴스 메소드들, 타입 메소드들, 연산자들, 인덱스참조(subscript) 등을 갖는 타입을 가져야한다.

      ### 프로토콜 문법
      프로토콜을 클래스, 구조체, 열거체와 매우 비슷한 방법으로 정의한다.

      ``` swfit
      protocol SomeProtocol {
      // 프로토콜 정의가 여기 온다
      }
      ```

      타입을 정의하는 곳에서 타입의 이름 뒤에 콜론(:)으로 구분해서 프로토콜의 이름을 써서 프로토콜을 커스텀 타입에 적용시킨다. 여러 프로토콜을 쉼표(,)로 구분해서 사용할 수 있다.

      ``` swift
      struct SomeStructure: FirstProtocol, AnotherProtocol {
      // 구조체 정의가 여기 온다
      }
      ```

      클래스가 부모를 가질 때는 프로토콜들 앞에 부모 클래스를 명시하고 쉼표로 구분해서 적용한다.

      ``` swift
      class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {
      // 클래스 정의가 여기 온다
      }
      ```

      ### 속성 요구사항
      프로토콜은 특정한 이름과 속성을 갖는 인스턴스 속성과 타입 속성을 제공하는 타입이 될 수 있다. 프로토콜에는 이 속성이 저장된 속성이어야하는지 계산된 속성이어야 하는지에 대해 명시하지 않는다. 단지 속성의 이름과 타입만 명시할 뿐이다. 또한 각 속성에 대해 읽기(gettable)인지 읽기/쓰기(gettable/settable)가 필요한지 명시할 수 한다.

      프로토콜의 속성에 읽기나 읽기/쓰기에 대한 명시가 있다면 그 속성은 저장된 상수값이나 읽기전용(read-only)의 계산된 값을 넣을 수 없다.
      만약 읽기가 필요하다고만 명시가 되어있고 어떤 종류의 속성도 가능하며 필요하면 읽기를 만들어도 괜찮다.

      속성 요구사항은 항상 `var` 키워드가 앞에 있는 변수 속성으로 선언된다. 읽기/쓰기 속성은 타입 뒤에 `{ get set }`을 써서 명시하며, 읽기는 `{ get }`으로 명시한다.

      ``` swift
      protocol SomeProtocol {
      var mustBeSettable: Int { get set }
      var doesNotNeedToBeSettable: Int { get }
      }
      ```

      타입 속성은 `class` 키워드를 붙여서 정의할 수 있다. 구조체나 열거형에서 구현할 때는 `static`을 붙이면 된다.

      ``` swift
      protocol AnotherProtocol {
      class var someTypeProperty: Int { get set }
      }
      ```

      인스턴스 속성 하나만 필요로 하는 프로토콜 예제가 있다.

      ``` swift
      protocol FullyNamed {
      var fullName: String { get }
      }
      ```

      `FullyNamed` 프로토콜은 이름이 맞으면 종류에 관계없는 속성을 정의한다. 어떤 `종류`여야하는지 명시하지는 않았고 그저 풀네임을 젱고할 수만 있으면 된다. `String` 타입의 읽기 가능한 `fullName`이라는 인스턴스 속성을 가진 `FullNamed`라는 요구사항만 명시되어있다.

      `FullyNamed` 프로토콜이 적용되어있고 일치하는 간단한 구조체 예제다.

      ``` swift
      struct Person: FullyNamed {
      var fullName: String
      }
      let john = Person(fullName: "John Appleseed")
      // john.fullName is "John Appleseed’
      ```

      이 예제에서는 `Person`이라고 불리는 구조체를 정의했고, 특정한 이름을 갖는다고 나타나있다. `FullyNamed` 프로토콜을 정의 첫번째 줄에 적용한 것이 보인다.


      `Person`의 인스턴스들은 `String` 타입의 `fullName` 속성 하나를 갖는다. `FullNamed` 프로토콜의 요구사항 하나와 일치하며, `Person`이 확실하게 프로토콜에 일치한다는 것을 의미한다. (스위프트에서는 프로토콜의 요구사항이 채워지지 않으면 컴파일타임에 에러를 낸다.)


      조금 더 복잡한 클래스가 있고, `FullNamed` 프로토콜을 적용했고 일치한다.

      ``` swift
      class Starship: FullyNamed {
      var prefix: String?
      var name: String
      init(name: String, prefix: String? = nil) {
      self.name = name
      self.prefix = prefix
      }
      var fullName: String {
      return (prefix ? prefix! + " " : "") + name
      }
      }
      var ncc1701 = Starship(name: "Enterprise", prefix: "USS")
      // ncc1701.fullName is "USS Enterprise’
      ```

      이 클래스에서는 계산된 읽기전용 속성으로 `fullName` 속성을 구현했다.
      각 `Starship` 클래스 인스턴스는 `name`을 필수로 `prefix`를 옵션으로 갖는다. `prefix` 값이 존재하면 `name`의 앞에 붙여서 우주선의 풀네임을 만들어 `fullName` 속성이 된다.


      ### 메소드 요구사항

      프로토콜은 일치하는 타입을 구현하기 위해 인스턴스 메소드들과 타입 메소드들을 요구사항으로 명시할 수 있다.
      중괄호나 메소드 구현체(body)만 없을 뿐, 일반적인 인스턴스 메소드나 타입 메소드를 정의하는 것과 정확히 같은 방법으로 정의된다.
      일반적인 메소드와 같은 규칙으로 가변길이의 변수도 가능하다.

      > 노트
      >
      > 프로토콜은 일반적인 메소드들과 같은 문법을 사용하지만 인자로 기본값을 명시할 수 없다.

      프로토콜에서 타입 속성을 정의할 때처럼 `class` 키워드를 타입 메소드 앞에 붙여주면 된다. 구조체나 열거형에서 구현할 때는 `static`을 붙여주면 된다.

      ``` swift
      protocol SomeProtocol {
      class func someTypeMethod()
      }
      ```

      인스턴스 메소드 하나만 있는 프로토콜의 예제다.

      ``` swift
      protocol RandomNumberGenerator {
      func random() -> Double
      }
      ```

      `RandomNumberGenerator` 프로토콜은 `Double`을 리턴하는 `random` 인스턴스 메소드를 갖는 어떤 타입에도 일치할 수 있다. (프로토콜에서는 명시되지 않았지만 `0.0`에서 `1.0` 사이의 값을 리턴할 것이라고 추정된다.)

      `RandomNumberGenerator` 프로토콜만으로는 어떻게 난수를 생성할지에 대한 정보가 없다. 단지 새로운 난수를 만들어서 제공하는 발생기를 필요로 할 뿐이다.

      `RandomNumberGenerator` 프로토콜을 적용하고 일치하는 클래스 구현체가 있다. *선형 합동 생성기(linear congruential generator)*라는 의사난수 생성 알고리즘을 구현했다.

      ``` swift
      class LinearCongruentialGenerator: RandomNumberGenerator {
      var lastRandom = 42.0
      let m = 139968.0
      let a = 3877.0
      let c = 29573.0
      func random() -> Double {
      lastRandom = ((lastRandom * a + c) % m)
      return lastRandom / m
      }
      }
      let generator = LinearCongruentialGenerator()
      println("Here's a random number: \(generator.random())")
      // prints "Here's a random number: 0.37464991998171"
      println("And another one: \(generator.random())")
      // prints "And another one: 0.729023776863283"
      ```

      ### 변이(mutating) 메소드

      가끔 메소드에서 자신의 인스턴스를 수정(혹은 *변이*)할 필요가 있다. 밸류 타입(즉, 구조체와 열거형)의 인스턴스 메소드에서 메소드의 `func` 앞에 `mutating` 키워드를 써서 소속된 인스턴스를 바꾸거나 인스턴스의 속성을 수정할 수 있게 명시한다. 이 과정은 [인스턴스 메소드 내에서 밸류 타입의 수정](#)에서 설졍되어있다.

      프로토콜이 적용된 타입의 인스턴스를 변이할 수 있다고 인스턴스 메소드에 명시하려면 프로토콜 정의세ㅓ `mutating` 키워드를 추가하면 된다. 이 프로토콜이 적용된 구조체와 열거형은 요구사항을 만족한다.

      > 노트
      >
      > 프로토콜을 `mutating`이라고 명시하면 클래스에서 메소드를 구현할 때는 `mutating` 키워드를 쓰지 않아도 된다.
      > `mutating` 키워드는 구조체와 열거형에서만 쓰인다.

      아래에는 `Togglable`이라는 프로토콜 예제인데, `toggle`이라는 인스턴스 메소드 하나만 정의되어있다. 이름에서 알 수 있듯 `toggle` 메소드는 보통 타입의 속성을 변환하는 것인데 프로토콜에 일치하는 타입의 속성을 토글하거나 반전한다.

      `toggle` 메소드는 `Togglable` 프로토콜 정의에서 `mutating` 키워드로 이 메소드를 호출했을 때 인스턴스의 상태가 변이될 것을 예상할 수 있다.

      ``` swift
      protocol Togglable {
      mutating func toggle()
      }
      ```

      `Togglable` 프로토콜을 구조체나 열거형으로 구현하려면, `mutating`이 명시된 `toggle` 메소드를 구현해야 프로토콜에 일치할 수 있다.

      아래 예제는 `OnOffSwitch`라는 열거형이다. 이 열거형은 `On`과 `Off` 두가지 상태 사이를 토글한다. 열거형의 `toggle` 구현체는 `Togglable` 프로토콜의 요구사항에 맞게 `mutating`이 명시되어 있다.

      ``` swift
      enum OnOffSwitch: Togglable {
      case Off, On
      mutating func toggle() {
      switch self {
      case Off:
      self = On
      case On:
      self = Off
      }
      }
      }
      var lightSwitch = OnOffSwitch.Off
      lightSwitch.toggle()
      // lightSwitch은 이제 .On과 같다.
      ```

      ### 타입으로서의 프로토콜
      프로토콜은 그 자체로 어떤 기능도 갖고 있지 않다. 하지만 어떤 프로토콜도 코드에서 다른 타입처럼 쓰일 수 있다.

      왜냐하면 프로토콜도 타입이므로 다른 타입들이 쓰이는 곳에서 사용될 수 있다.
      - 함수, 메소드, 생성자에서 인자의 타입 혹은 리턴 타입으로
      - 상수, 변수, 속성의 타입으로
      - 배열, 사전, 다른 컨테이너에서 요소의 타입으로
      사용될 수 있다.

      > 노트
      >
      > 프로토콜이 타입이므로 스위프트의 다른 타입(`Int`, `String`, `Double`같은)처럼 이름을 대문자(`FullyNamed`나 `RandomNumberGenerator`처럼)로 사용할 수 있다.

      타입으로 프로토콜을 사용하는 예제다.

      ``` swift
      class Dice {
      let sides: Int
      let generator: RandomNumberGenerator
      init(sides: Int, generator: RandomNumberGenerator) {
      self.sides = sides
      self.generator = generator
      }
      func roll() -> Int {
      return Int(generator.random() * Double(sides)) + 1
      }
      }
      ```

      이 예제에서는 *n*면체의 `Dice`라는 새로운 클래스가 정의되어있다. `Dice`의 인스턴스는 면을 얼마나 가지고 있는지를 나타내는 `sides`라는 정수 속성과 주사위를 굴렸을 때 난수를 생성해주는 `generator` 속성을 가지고 있다.

      `generator` 속성은 `RandomNumberGenerator` 타입의 속성이다. 그러므로 `RandomNumberGenerator` 프로토콜을 적용한 *어떤* 타입의 인스턴스라도 할당할 수 있다.

      `Dice`는 초기 상태를 설정하는 생성자도 가지고 있다. 생성자는 `RandomNumberGenerator` 타입의 `generator`를 인자로 받는다.
      새로운 `Dice` 인스턴스를 만들 때 프로토콜에 일치하는 어떤 타입도 인자로 넘길 수 있다.

      `Dice`는 하나의 인스턴스 메소드 `roll`이 있는데, 1에서 면의 수 사이에 해당하는 정수를 리턴한다. 이 메소드에서는 생성기의 `random` 메소드를 호출해서 `0.0`과 `1.0` 사이의 난수를 받아 정확한 범위의 값을 만든다. `generator`가 `RandomNumberGenerator`를 적용하고 있기 때문에 확실하게 `rondom` 메소드를 가지고 있다.


      여기 `LinearCongruentialGenerator` 인스턴스를 난수생성기로 받는 6면체의 `Dice` 클래스가 어떻게 사용되는지 예제가 있다.

      ``` swift
      var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
      for _ in 1...5 {
      println("랜덤한 주사위값은 \(d6.roll())")
      }
      // 랜덤한 주사위값은 3
      // 랜덤한 주사위값은 5
      // 랜덤한 주사위값은 4
      // 랜덤한 주사위값은 5
      // 랜덤한 주사위값은 4
      ‌```

      ### 위임 (Delegation)
      위임은 클래스나 구조체가 다른 타입의 인스턴스에게 책임의 일부를 넘길(혹은 *위임할*) 수 있는 디자인 패턴이다. 이 디자인 패턴에서는 위임된 책임을 캡슐화하는 프로토콜을 정의하는데, 거기에 일치하는 타입(대리자delegate로 알려진)은 위임받은 기능이 있다고 보장된다. 위임은 특정 액션에 대해 응답하거나, 외부에서 온 정보가 어떤 타입인지에 관계없이 데이터를 처리할 때 사용할 수 있다.

      아래에 주사위를 사용한 보드게임에 두가지 프로토콜이 정의되어있다.

      ``` swift
      protocol DiceGame {
      var dice: Dice { get }
      func play()
      }
      protocol DiceGameDelegate {
      func gameDidStart(game: DiceGame)
      func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
      func gameDidEnd(game: DiceGame)
      }
      ```

      `DiceGame` 프로토콜은 주사위를 포함하는 어떤 게임에도 적용할 수 있는 프로토콜이다. `DiceGameDelegate` 프로토콜은 `DiceGame`의 진행을 기록할 수 있는 어떤 타입에도 적용할 수 있는 프로토콜이다.

      앞서 [흐름 제어](#)에서 소개되었던 *뱀과 사다리*의 수정 버전이다. 이 버전에서는 주사위 굴리기를 위해 `Dice` 인스턴스를 사용한 `DiceGame` 프로토콜을 적용했고 과정을 `DiceGameDelegate`에 알리기 위해 `DiceGame` 프로토콜을 적용했다.

      ``` swift
      class SnakesAndLadders: DiceGame {
      let finalSquare = 25
      let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
      var square = 0
      var board: Int[]
      init() {
      board = Int[](count: finalSquare + 1, repeatedValue: 0)
      board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
      board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
      }
      var delegate: DiceGameDelegate?
      func play() {
      square = 0
      delegate?.gameDidStart(self)
      gameLoop: while square != finalSquare {
      let diceRoll = dice.roll()
      delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
      switch square + diceRoll {
      case finalSquare:
      break gameLoop
      case let newSquare where newSquare > finalSquare:
      continue gameLoop
      default:
      square += diceRoll
      square += board[square]
      }
      }
      delegate?.gameDidEnd(self)
      }
      }
      ```

      *뱀과 사다리* 게임에 대한 설명을 원하면 [흐름 제어](#) 챕터의 [break](#) 섹션에 나와있다.

      이 버전에서는 `DiceGame`을 적용한 `SnakesAndLadders`라는 클래스로 이루어졌다. `dice` 속성과 `play` 메소드을 가지고 있어 프로토콜에 일치한다. (`dice` 속성은 상수 속성으로 선언되었는데, 일단 생성되고 난 뒤에 변경될 필요가 없으며 프로토콜의 요구는 읽기만 가능하면 된다.)

      *뱀과 사다리* 게임보드 설정은 클래스의 `init()` 생성자 내에서 이루어진다. 게임 로직 전체는 프로토콜의 `play` 메소드 내로 옮겨졌고, 주사위를 굴린 값을 얻기 위해 `dice` 속성을 필요로 하는 프로토콜을 사용한다.

      `delegate` 속성은 `DiceGameDelegate` 옵션으로 되어있는데, 게임을 실행하는데 대리자가 꼭 필요하지는 않아서이다. 옵션값이기 때문에 `delegate` 속성은 자동으로 `nil`을 초기값으로 받는다. 그리고 나서 게임을 초기화할 때 적절한 위임자를 속성으로 받을 수도 있다.

      `DiceGameDelegate`는 게임의 진행을 기록하기 위해 3가지 메소드를 제공한다. `play` 메소드 내부에서 사용되며 새로운 게임을 시작할 때, 턴이 시작될 때, 게임이 끝날 때 호출된다.

      `delegate` 속성은 `DiceGameDelegate` 타입의 옵션값이기 때문에 `play` 메소드는 대리자에서 메소드를 호출할 때마다 옵션 연쇄를 사용한다. `delegate` 속성이 nil이면, 이 대리자는 에러없이 호출을 실패한다. `deleagte` 속성이 nil이 아니면 메소드를 호출하고 `SnakesAndLadders` 인스턴스를 인자로 넘긴다.

      다음 예제는 `DiceGameTracker`라는 클래스로, `DiceGameDelegate` 프로토콜이 적용되었다.

      ``` swift
      class DiceGameTracker: DiceGameDelegate {
      var numberOfTurns = 0
      func gameDidStart(game: DiceGame) {
      numberOfTurns = 0
      if game is SnakesAndLadders {
      println("뱀과 사다리의 새 게임을 시작한다")
      }
      println("게임은 \(game.dice.sides)면체 주사위를 사용할 것이다")
      }
      func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
      ++numberOfTurns
      println("주사위는 \(diceRoll)")
      }
      func gameDidEnd(game: DiceGame) {
      println("게임은 \(numberOfTurns)턴을 사용했다")
      }
      }
      ```

      `DiceGameTracker`에서는 `DiceGameDelegate`에서 필요한 세가지 메소드를 모두 구현되어있다. 세가지 메소드를 사용해서 게임에서 몇턴이 진행되었는지 기록한다. 게임이 시작하면 `numberOfTurns` 속성을 0을 초괴화하고, 새 턴이 시작할 때마다 증가시키고, 게임이 끝났을 때 총 몇턴이 지났는지 출력한다.

      위에서 나온 `gameDidStart`의 구현에서는 `game` 인자를 사용해 게임을 플레이하려고 할 때 안내 문구를 출력한다. `game` 인자는 `SnakesAndLadders`타입이 아니라 `DiceGame`타입을 갖는다. `gameDidStart`는 `DiceGame` 프로토콜에 있는 메소드와 속성들만 사용하고 접근한다. 하지만 메소드에서는 타입 케스팅을 통해 인스턴스가 어떤 타입인지 확인할 수도 있다. 이 예제에서는 `game`이 실제로 `SnakesAndLadders`의 인스턴스인지 확인하고 맞다면 적절한 문구를 출력한다.


      `gameDidStart`는 인자로 받은 `game`의 `dice` 속성에도 접근한다. `game`은 `DiceGame` 프로토콜에 일치한다고 되어있으니 `dice` 속성을 가지고 있을 것이고 `gameDidStart` 메소드는 어떤 종류의 게임인지에 관계없이 주사위의 `sides` 속성을 출력할 수 있다.

      `DiceGameTracker`가 어떻게 작동하는지 아래 있다.

      ``` swift
      let tracker = DiceGameTracker()
      let game = SnakesAndLadders()
      game.delegate = tracker
      game.play()
      // 뱀과 사다리 새 게임을 시작한다
      // 게임은 6면체 주사위를 사용할 것이다
      // 주사위는 3
      // 주사위는 5
      // 주사위는 4
      // 주사위는 5
      // 게임은 4턴을 사용했다
      ```


      ### 확장을 프로토콜 일치에 추가

      이미 존재하는 타입의 소스에 접근할 수 없어도 그 타입에 프로토콜을 적용하고 일치하도록 확장할 수 있다.
      확장은 새 속성들, 메소드들, 인덱스 참조 등을 이미 존재하는 타입에 추가할 수 있고, 프로토콜에서 필요로 하는 요구사항들을 추가할 수도 있다.
      확장에 대해 더 많은 정보는 [확장](#) 챕터에 있다.

      > 노트
      >
      > 확장을 타입에 추가하는 순간 이미 만들어놓은 인스턴스들에서도 프로토콜이 적용되고 일치하게 된다.

      예를 들어, `TextRepresentable`이라는 프로토콜은 타입을 텍스트로 표현하는 방법을 구현할 수 있다. 인스턴스의 설명이 될 수도 있고, 현재 상태의 텍스트 표현이 될 수도 있다.

      ``` swift
      protocol TextRepresentable {
      func asText() -> String
      }
      ```

      위에서 본 `Dice` 클래스에 `TextRepresentable`을 적용하고 일치시킬 수 있다.

      ``` swift
      extension Dice: TextRepresentable {
      func asText() -> String {
      return "\(sides)면체 주사위"
      }
      }
      ```

      확장은 `Dice`를 위에서 구현했던 것과 정확히 같은 방법으로 새로운 프로토콜을 적용한다. 프로토콜 이름 뒤에 콜론으로 구분해서 프로토콜의 이름을 적고 중괄호 안에 프로토콜의 요구사항들 전부를 구현하면 된다.

      이제 어떤 `Dice` 인스턴스들도 `TextRepresentable`로 처리할 수 있다.


      ```
      let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
      println(d12.asText())
      // "12면체 주사위" 출력
      ```

      비슷하게 `SnakesAndLadders` 게임 클래스도 `TextRepresentable` 프로토콜을 적용하고 일치하도록 확장할 수 있다.

      ``` swift
      extension SnakesAndLadders: TextRepresentable {
      funcs asText() -> String {
      return "뱀과 사다리 게임은 \(finalSquare)"칸
      }
      }
      println(game.asText())
      // "뱀과 사다리 게임은 25칸" 출력
      ```


      ### 확장과 동시에 프로토콜 적용 선언

      타입이 이미 프로토콜의 모든 요구사항에 일치하고 있지만 프로토콜을 적용한다고 명시하지 않았을 때, 빈 확장과 함께 프로토콜을 적용시킬 수 있다.

      ``` swift
      struct Hamster {
      var name: String
      func asText() -> String {
      return "햄스터 이름은 \(name)"
      }
      }
      extension Hamster: TextRepresentable {}
      ```

      이제 `Hamster`의 인스턴스들은 `TextRepresentable`을 타입으로 사용할 수 있다.

      ``` swift
      let simonTheHamster = Hamster(name: "Simon")
      let somethingTextRepresentable: TextRepresentable = simonTheHamster
      println(somethingTextRepresentable.asText())
      // "햄스터 이름은 Simon" 출력
      ```

      > 노트
      >
      > 타입에서 요구사항을 만족했다고 자동으로 프토토콜이 적용되지는 않는다. 항상 명시적으로 프로토콜의 적용을 선언해줘야 한다.


      ### 프로토콜 타입의 콜렉션(Collection)들

      프로토콜은 [타입으로서의 프로토콜](#)에서 이야기한 것처럼 배열이나 사전같은 콜렉션에 저장되는 타입으로 사용할 수 있다.
      여기 `TextRepresentable`의 배열을 만든 예제가 있다.

      ``` swift
      let things: TextRepresentable[] = [game, d12, simonTheHamster]
      ```

      배열에서 아이템들을 반복하면서 각 아이템을 텍스트로 출력하는 것이 가능하다.

      ``` swift
      for thing in things {
      println(thing.asText())
      }
      // 뱀과 사다리 게임은 25칸
      // 12면체 주사위
      // 햄스터 이름은 Simon
      ```

      `thing` 상수는 `Dice`나 `DiceGame`이나 `Hamster` 타입이 아니고 `TextRepresentable` 타입이다. 하지만 `TextRepresentable`은 `asText` 메소드를 가지고 있기 때문에 반복문에서 `thing.asText`를 안전하게 호출할 수 있다.

      ### 프로토콜 상속

      프로토콜은 하나 이상의 프로토콜을 *상속*받을 수 있고, 그 요구사항들 위에 다른 요구사항을 추가할 수도 있다. 프로토콜 상속 문법은 클래스 상속의 문법과 비슷하지만 쉼표를 구분해서 여러 프로토콜을 나열할 수 있다.

      ``` swift
      protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
      // 프로토콜 정의가 여기 온다
      }
      ```

      위의 `TextRepresentable` 프로토콜을 상속받는 예제가 있다.

      ``` swift
      protocol PrettyTextRepresentable: TextRepresentable {
      func asPrettyText() -> String
      }
      ```

      이 예제에서는 `TextRepresentable`을 상속받는 `PrettyTextRepresentable`라는 새로운 프로토콜을 정의한다. `PrettyTextRepresentable`을 적용한 것들은 `TextRepresentable`의 요구사항을 모두 만족해야하고, 추가로 `PrettyTextRepresentable`의 요구사항도 만족해야한다. 이 예제에서는 `String`을 리턴하는 `asPrettyText`라는 인스턴스 메소드 하나가 요구사항으로 추가되었다.

      `PrettyTextRepresentable`를 적용하고 일치하게 `SnakesAndLadders` 클래스를 확장할 수 있다.

      ``` swift
      extension SnakesAndLadders: PrettyTextRepresentable {
      func asPrettyText() -> String {
      var output = asText() + ":¶
      "
      for index in 1...finalSquare {
      switch board[index] {
      case let ladder where ladder > 0:
      output += "▲ "
      case let snake where snake < 0:
      output += "▼ "
      default:
      output += "○ "
      }
      }
      return output
      }
      }
      ```

      이 확장은 `PrettyTextRepresentable` 프로토콜을 적용하고 `SnakesAndLadders` 타입에서 `asPrettyText` 메소드를 구현했다. `PrettyTextRepresentable`가 적용되었다면 `TextRepresentable`도 적용해야하므로, `asPrettyText`의 구현이 `TextRepresentable`의 `asText` 메소드를 호출하는 것으로 시작한다. `asText`에 콜론과 줄넘김을 붙이는 것을 시작으로 출력값을 만든다. 보드의 배열을 돌면서 각 칸에 해당하는 특수문자(emoji)를 붙인다.

      - 칸의 값이 0보다 크고 사다리면 ▲로 표시
      - 칸의 값이 0보다 작고 뱀 머리면 ▼로 표시
      - 그 외에, 칸의 값이 0이고 "비어있는" 칸이면 ○으로 표시

      이제 메소드구현으로 `SnakesAndLadders` 인스턴스의 내역을 보기좋게 표시하는데 사용할 수 있다.

      ``` swift
      println(game.asPrettyText())
      // 뱀과 사다리 게임은 25칸:
      // ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○
      ```


      ### 프로토콜 합성

      한번에 여러 프로토콜에 일치하는 타입이 필요할 때 유용하게 쓸 수 있다. *프로토콜 합성*으로 여러 프로토콜을 하나의 요구사항으로 합칠 수 있다. 프로토콜 합성은 `protocol`같은 형태를 가진다. 꺾쇠(<>) 안에 쉼표로 구분해서 원하는만큼 프로토콜을 명시할 수 있다.

      여기 `Named`와 `Aged` 두가지 프로토콜을 합성해서 하나의 함수 파라미터로 사용하는 예제가 있다.

      ``` swift
      protocol Named {
      var name: String { get }
      }
      protocol Aged {
      var age: Int { get }
      }
      struct Person: Named, Aged {
      var name: String
      var age: Int
      }
      func wishHappyBirthday(celebrator: protocol) {
      println("\(celebrator.name)의 \(celebrator.age)번째 생일을 축하합니다!")
      }
      let birthdayPerson = Person(name: "Malcolm", age: 21)
      wishHappyBirthday(birthdayPerson)
      // "Malcolm의 21번째 생일을 축하합니다!" 출력
      ```

      이 예제에서는 `String` 타입의 `name`이라는 읽기 속성 하나를 요구사항으로 가지는 `Named`라는 프로토콜을 정의한다. 또한 `Int` 타입의 `age`라는 읽기 속성 하나를 요구사항으로 가지는 `Aged`도 정의한다. 두 프로토콜 모두 `Person` 구조체에 적용된다.

      `wishHappyBirthday`라는 함수를 만들어서 `celebrator`라는 인자를 하나 받는다. 이 인자의 타입은 `protocol`이며 "`Named`와 `Aged` 프로토콜에 모두 일치하는 어떤 타입"을 의미한다. 어떤 특정한 타입이 인자로 넘어오는지는 관계없으나 요구하는 프로토콜 양쪽 다 일치해야한다.


      그리고나서 `birthdayPerson`이라는 `Person`의 인스턴스를 만들어서 `wishHappyBirthday`라는 함수의 인자로 넘긴다. `Person`이 프로토콜 양쪽 다 일치하기 때문에 유효하며 `wishHappyBirthday` 함수에서 생일축하 인사를 출력할 수 있다.

      > 노트
      >
      > 프로토콜 합성은 새로 영구적으로 프토토콜 타입을 만드는 것이 아니다. 합성에 있는 모든 프로토콜의 요구사항을 합친 하나의 프로토콜을 임시로 만드는 것이다.


      ### 프로토콜 일치를 확인하기

      [타입 캐스팅](#)에서 설명했던 것처럼 특정 프로토콜로 캐스팅하기 위해서 프로토콜 일치를 확인하는데 `is`와 `as` 연산자를 사용할 수 있다. 타입을 확인하고 캐스팅하는 것과 정확히 같은 방법으로 프로토콜을 확인하고 캐스팅할 수 있다.

      - `is` 연산자에서는 인스턴스가 프로토콜과 일치하면 `true`, 아니면 `false`를 리턴
      - 'as?' 다운캐스팅 연산자는 프로토콜 타입의 옵션값을 리턴하는데 인스턴스가 프로토콜과 일치하지 않으면 `nil`이 된다
      - `as` 연산자는 강제로 다운캐스팅하고 실패하면 런타임 에러가 난다.

      `Double` 타입의 `area` 읽기 속성 하나를 요구사항으로 갖는 `HasArea` 프로토콜 예제가 있다.

      ``` swift
      @objc protocol HasArea {
      var area: Double { get }
      }
      ```

      > 노트
      >
      > `HasArea` 프로토콜 앞에 보이듯 프로토콜 일치를 확인하기 위해서는 `@objc` 속성(attribute)을 명시해줘야한다.
      > *코코아와 Objective-C를 스위프트와 사용하기(Using Swift with Cocoa and Objective-C)*에서 설명하듯 이 속성은 Objective-C 코드에서 인식할 수 있을 것이라는 것을 명시한다.
      > Objective-C를 함께 쓰지 않더라도 프로토콜 일치를 확인하고 싶다면 `objc`를 프로토콜에 명시해줘야한다.
      >
      > `@objc` 프로토콜은 구조체나 열거형은 불가능하고 클래스에만 적용할 수 있다.

      `HasArea` 프로토콜과 일치하는 `Circle`과 `Country` 두가지 클래스가 있다.

      ``` swift
      class Circle: HasArea {
      let pi = 3.1415927
      var radius: Double
      var area: Double { return pi * radius * radius }
      init(radius: Double) { self.radius = radius }
      }
      class Country: HasArea {
      var area: Double
      init(area: Double) { self.area = area }
      }
      ```

      `Circle` 클래스는 저장된 `radius` 속성을 사용해 `area` 속성을 계산된 속성으로 구현했다. `Country` 클래스에서는 직접 저장된 속성으로 `area` 속성을 구현했다. 두가지 클래스 모두 `HasArea` 프로토콜에 정확히 일치한다.

      여기 `Animal`이라는 클래스가 있고 `HasArea` 프로토콜에 일치하지 않는다.

      ```
      class Animal {
      var legs: Int
      init(legs: Int) { self.legs = legs }
      }
      ```

      `Circle`, `Country`, `Animal` 클래스는 공통된 부모 클래스를 갖지는 않는다. 다만 이 클래스들과 클래스들의 인스턴스들 모두 `AnyObject` 배열의 값으로 초기화되는데 사용할 수 있다.


      ``` swift
      let objects: AnyObject[] = [
      Circle(radius: 2.0),
      Country(area: 243_610),
      Animal(legs: 4)
      ]
      ```

      `Circle` 인스턴스는 반지름 2로, `Country` 인스턴스는 영국의 면적으로, `Animal` 인스턴스는 다리 4개로 초시화되어 배열 표기를 통해 `objects` 배열에 초기화되었다.

      `objects` 배열은 순환가능하며, 배열 내 각각의 객체는 `HasArea` 프로토콜에 일치하는지 확인할 수 있다.

      ``` swift
      for object in objects {
      if let objectWithArea = object as? HasArea {
      println("넓이는 \(objectWithArea.area)")
      } else {
      println("넓이를 가지고 있지 않다")
      }
      }
      // 넓이는 12.5663708
      // 넓이는 243610.0
      // 넓이를 가지고 있지 않다
      ```

      배열 내의 객체가 `HasArea` 프로토콜에 일치할 때마다 `as?` 연산자를 통해 `objectWithArea`라는 상수값으로 옵션값을 받을 수 있다. `objectWithArea` 상수는 `HasArea` 타입이며 `area` 속성을 접근할 수도 있고 출력도 가능하다.

      캐스팅 과정에서 객체들이 변하지는 않는다. 여전히 `Circle`, `Country`, `Animal` 객체다. 하지만 `objectWithArea` 상수에 저장되면 `HasArea` 타입으로만 사용할 수 있고 `area` 속성에만 접근할 수 있다.

      ### 프로토콜 선택적 요구사항

      프로토콜에서 *선택적 요구사항*을 정의할 수 있다. 프로토콜에 일치하기 위해서 이 요구사항들을 구현하지 않아도 된다. 선택적 요구사항들은 정의 앞에 `@optional` 키워드가 붙는다.

      선택적 요구사항은 프로토콜에 일치하도록 요구사항이 구현되었는지 여부를 확인하는 옵션 연쇄와 같이 사용될 수 있다. 옵션 연쇄에 대해서는 [옵션 연쇄](#) 챕터에 정보가 나와있다.

      요구사항(의 메소드나 이름)이 쓰일 때 `someOptionalMethod?(someArgument)`처럼 이름 뒤에 물음표가 붙는 구현을 확인할 수 있다.
      선택적 속성 요구사항과 값을 리턴하는 선택적 메소드 요구사항은 그걸 접근해서 호출할 때 적절한 타입의 옵션값을 항상 반환하며, 구현이 되어있지 않을 수 있는 선택적 요구사항의 상태를 보여준다.

      > 노트
      >
      > 프로토콜의 선택적 요구사항들은 `@objc` 속성이 명시되어있을 때만 사용할 수 있다.
      > Objective-C와 같이 사용하지 않더라도 선택적 요구사항을 사용하고 싶다면 `@objc` 속성을 명시해야한다.
      >
      > 구조체나 열거형이 아닌 클래스에서만 `@objc` 프로토콜을 적용할 수 있다.
      > 따라서 선택적 요구사항을 사용하기 위해 `@objc`를 프로토콜에 명시했다면 프로토콜은 클래스 타입에만 적용될 수 있다.


      다음 예제는 `Counter`라는 정수 카운터를 구현한 것으로 증가량을 외부에 제공하기 위해 사용한다. 선택적 요구사항 2가지를 가진 `CounterDataSource` 프로토콜이 정의되어있다.

      ``` swift
      @objc protocol CounterDataSource {
      @optional func incrementForCount(count: Int) -> Int
      @optional var fixedIncrement: Int { get }
      }
      ```

      `CounterDataSource` 프로토콜에는 `incrementForCount`라는 선택적 메소드 요구사항과 `fixedIncrement`라는 선택적 속성 요구사항이 정의되어있다.
      이 요구사항들은 `Counter` 인스턴스에 증가량을 전하기 위한 두가지 방법이다.

      > 노트
      >
      > 엄밀히 이야기해서 프로토콜 요구사항을 *전혀* 구현하지 않고도 `CounterDataSource`에 일치하는 클래스를 만들 수 있다.
      > 둘 다 선택적 요구사항이기 때문이다. 기술적으로는 가능하지만 괜찮은 방법은 아니다.

      아래 정의한 `Counter` 클래스는 `CounterDataSource?` 타입을 `dataSource`라는 선택적 속성으로 가지고 있다.

      ```
      @objc class Counter {
      var count = 0
      var dataSource: CounterDataSource?
      func increment() {
      if let amount = dataSource?.incrementForCount?(count) {
      count += amount
      } else if let amount = dataSource?.fixedIncrement? {
      count += amount
      }
      }
      }
      ```

      `Counter` 클래스는 `count` 속성에 현재값을 저장한다.
      그리고 `increment`라는 메소드도 가지고 있는데 불릴 때마다 `count` 속성을 증가시킨다.

      `increment` 메소드는 데이터 소스에서 `incrementForCount`가 구현되어있는지 확인하고 증가량을 가져온다. 옵션 연쇄로 `count`를 인자로 넘기는 `incrementForCount`를 호출한다.

      여기 *두* 단계의 옵션 연쇄가 있다. 첫번째로는 `dataSource`가 `nil`일 수도 있으니 아닐 때만 `incrementForCount`를 호출하기 위해 물음표가 붙어있다. 두번째로는 `dataSource`가 *존재하긴* 하지만 선택적 요구사항인 `incrementForCount`가 구현되어있다는 보장이 없다. 그래서 `incrementForCount`에도 물음표가 붙어 있다.

      `incrementForCount`를 호출하는데 두가지 이유로 실패할 수 있어서 *선택적* `Int`값이 리턴된다. 참이면 `incrementForCount`가 구현되어 있어서 `CounterDataSource` 정의에 따라 비선택적(non-optional) `Int` 값을 받는다.

      `incrementForCount`가 호출되고 나면 실제로 받은 `Int` 값이 `amount`에 상수로 들어간다. 만약 선택적 `Int`가 값을 가지고 있으면, 즉 대리자와 메소드가 둘 다 존재하면 메소드는 값을 리턴할테니 `amount`의 실제값이 `count` 속성에 더해져 저장되고, 증가는 완료된다.

      `dataSource`가 nil이거나 `incrementForCount`를 구현하지 않아서 `incrementForCount`에서 값을 가져올 수 *없다면* `increment` 메소드는 `fixedIncrement` 속성을 대신 가져온다.
      `fixedIncrement` 속성은 선택적 요구사항이므로 끝에 물음표를 붙여서 실패할 수 있는 것을 명시한다. 앞에서처럼 `CounterDataSource` 프로토콜의 정의에서 `fixedIncrement`는 비선택적 `Int` 속성이지만, 결과적으로 선택적 `Int` 값이 리턴된다.

      호출될 때마다 `3`을 리턴하는 간단한 `CounterDataSource` 구현이 있다. 선택적 `fixedIncrement` 속성을 구현했다.

      ``` swift
      class ThreeSource: CounterDataSource {
      let fixedIncrement = 3
      }
      ```

      `ThreeSource`의 인스턴스를 새로운 `Counter` 인스턴스의 데이터 소스로 사용할 수 있다.

      ``` swift
      var counter = Counter()
      counter.dataSource = ThreeSource()
      for _ in 1...4 {
      counter.increment()
      println(counter.count)
      }
      // 3
      // 6
      // 9
      // 12
      ```

      새로운 `Counter` 인스턴스를 만드는 위의 코드에서는 `ThreeSource` 인스턴스를 데이터 소스로 사용하고, `increment` 메소드를 4번 호출한다. 예상대로 카운터의 `count` 속성은 `increment`가 호출되는 3번동안 증가한다.

      여기 `TowardsZeroSource`라는 조금 더 복잡한 데이터 소스가 있다. `Counter` 인스턴스에서는 현재 `count` 값에서 0을 향해 올리거나 내린다.

      ``` swift
      class TowardsZeroSource: CounterDataSource {
      func incrementForCount(count: Int) -> Int {
      if count == 0 {
      return 0
      } else if count < 0 {
      return 1
      } else {
      return -1
      }
      }
      }
      ```

      `TowardsZeroSource` 클래스는 `CounterDataSource` 프로토콜의 선택적 `incrementForCount` 메소드를 구현했고 `count` 인자값을 사용해 0을 향하도록 한다. `count`가 이미 0이면 더이상 카운트할 필요가 없다고 명시하도록 `0`을 리턴한다.

      `Counter` 인스턴스에 `TowardsZeroSource` 인스턴스를 상요해서 `-4`에서 0까지 증가시킨다. 카운터가 0에 도달하면 더이상 카운트하지 않는다.

      ``` swift
      Counter.count = -4
      counter.dataSource = TowardsZeroSource()
      for _ in 1...5 {
      counter.increment()
      println(counter.count)
      }
      // -3
      // -2
      // -1
      // 0
      // 0
      ```