fullName
프로퍼티는 저장된 프로퍼티로 사용될 수 있고,random()
을 구현한 클래스입니다.NOTE 프로토콜에 mutating을 명시한 경우 이 프로토콜을 따르는 클래스 형을 구현할 때는 메소드에 mutating을 명시하지 않아도 됩니다. mutating은 값타입 형에만 사용합니다.
toggle()
메소드를 변경해 사용할 수 있습니다.NOTE 클래스 타입에서 final로 선언된 것에는 required를 표시하지 않아도 됩니다. final로 선언되면 서브클래싱 되지 않기 때문입니다.
NOTE 프로토콜은 타입이기 때문에 위 예제의 FullyNamed, RandomNumberGenerator와 같이 첫 글자를 대문자로 적어줍니다.
delegate?.gameDidStart(self)
, delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
, delegate?.gameDidEnd(self)
를 실행합니다. delegate는 게임을 진행시키는데 반드시 필요한 건 아니라서 옵셔널로 정의돼 있습니다. 아래는 실제 DiceGameDelegate를 상속하는 delegate DiceGameTracker를 구현한 예입니다.NOTE 이미 존재하는 타입에 익스텐션이 추가되면 자동으로 그 타입에서 추가된 익스텐션의 기능을 사용할 수 있습니다.
d12.textualDescription
같이 Dice에 추가한 익스텐션을 자동으로 그대로 사용할 수 있습니다.textualDescription
프로퍼티를 사용할 수 있습니다. textualDescription는 Array의 모든 아이템을 순회하고 각각의 textualDescription
를 결합해 반환하는 메소드입니다.NOTE 프로토콜의 요구사항을 기술하는 것만으로 프로토콜 사용의 조건을 충족시킬 수 없습니다. 반드시 어떤 프로토콜을 따르는지에 대해 기술해야 합니다.
NOTE 참조 구문만 필요한 프로토콜을 정의하기 위해 클래스 전용 프로토콜을 사용합니다.
is
연산자를 이용하면 어떤 타입이 특정 프로토콜을 따르는지 확인할 수 있습니다. 특정 프로토콜을 따르면 true를 아니면 false를 반환합니다.as?
는 특정 프로토콜 타입을 따르는 경우 그 옵셔널 타입의 프로토콜 타입으로 다운캐스트를 하게 되고 따르지 않는 경우는 nil을 반환합니다.as!
는 강제로 특정 프로토콜을 따르도록 정의합니다. 만약 다운캐스트에 실패하면 런타임 에러가 발생합니다.as? HasArea
구문을 사용해 HasArea프로토콜을 따르는지 확인하고 따르는 경우 HasArea 타입으로 다운캐스트 합니다.NOTE 엄격하게 말해 CounterDataSource를 따르면서 구현은 하나도 하지 않는 클래스를 선언할 수는 있습니다. 기술적으로는 가능하지만 이렇게 구현하는 것은 좋은 방법이 아닙니다. 만약 하나도 구현하지 않는다면 필요하지 않다는 것 이므로 굳이 CounterDataSource 프로토콜을 따르도록 선언할 필요가 없습니다.
increment?(forCount: count)
와 fixedIncrement
는 옵셔널이므로 구현이 안돼있을 수 있기 때문에 옵셔널 체이닝을 이용해 확인해 봅니다. 다음 코드는 CounterDataSource를 따르는 예입니다.counter.increment()
가 호출될때마다 0에 가까워지면서 결국 0에 수렴하게 됩니다.random()
을 따르는 RandomNumberGenerator에 randomBool()
을 따르도록 추가한 예입니다.generator.random()
과 generator.randomBool()
를 둘다 이용할 수 있음을 확인할 수 있습니다.NOTE 프로토콜 익스텐션에 의해 구현된 기본 구현은 옵셔널 요구조건과 다릅니다. 둘다 꼭 구현하지 않아도 되는 것은 같지만 사용시 기본 구현은 옵셔널 체이닝을 사용하지 않아도 됩니다.
allEqual()
메소드를 구현한 예입니다.allEqual()
를 호출할 수 있습니다.