Merge changes from Quartet into master

Quartet authored
revision 51f8126b4c4a255c141b9fc38cacfb4bfd4a544d
chapter14
# 14 서브스크립트 (Subscripts)
> Translator : Snowcat8436 (snowcat8436@gmail.com)

클래스, 구조체 그리고 열거형은 collection, list, sequence의 member element에 접근하기 위한 축약형인 _서브스크립트_로 정의할 수 있습니다. 또한 값의 설정이나 검색을 위한 별도의 메서드(seperate method)없이 index를 통해서 값을 설정하거나 검색하기 위해 서브스크립트를 사용할 수있습니다. 예를 들어서 `someArray[index]`와 같이 `배열`의 내부값(element)에 접근하거나 `someDictionary[key]`와 같이 사용하여 `딕셔너리`의 내부값(element)에 접근할 수 있습니다.

한 타입을 위해서 여러개의 서브스크립트를 정의 할 수도 있고, 또한
서브스크립트로 넘기는 index값의 타입을 기초로하여 사용하기 적절한 서브스크립트 overload(중복)를 선택할수 있다. 서브스크립트는 당신이 원하는 타입에 맞게 여러개의 입력 파라미터(input parameter)를 가지도록 정의할 수도 있다.

## 서브스크립트 문법(Subscript Syntax)

서브스크립트는 인스턴스의 이름 뒤에 있는 '[]'안에 한개 이상의 값을 적는 것으로 당신이 인스턴스들의 타입(instances of a type)를 요구할 수 있다. 그들의 문법은 인스턴스의 메서드나 computed property의 문법과 유사합니다. 인스턴스의 메서드들과 동일한 방식으로 `subscript`키워드와 함께 특정한 하나 이상의 입력 파라미터와 와 리턴타입을 통해서 서브스크립트를 정의할 수 있다. 다만 인스턴스의 메서드들과는 달리 서브스크립트는 읽고 쓰는 권한만 있거나 읽는 권한만을 가질 수 있다. 다음 코드는 서브스크립트가 computed property들과 동일한 방식으로 getter와 setter를 통해 작업하는 것을 보여줍니다
```
subscript(index: Int) -> Int {
get {
// return an appropriate subscript value here
}
set(newValue) {
// perform a suitable setting action here
}
}
```
`newValue`의 type은 해당 subscript의 리턴값과 동일합니다.
computed properties와 같이 당신은 setter의 파라미터인 `(newValue)`를 특정하게 선택할수 없습니다. 만일 당신이 setter를 위한 타입을 아무것도 제공하지 않는다면, 그제서야 기본 parameter인 `newValue`가 setter를 위해 제공될 것입니다.

읽기 전용의 computed properties와 같이 `get` 키워드를 없애서 읽기 전용의 서브스크립트를 만들 수 있다.:
```
subscript(index: Int) -> Int {
// return an appropriate subscript value here
}
```
이곳에 정수를 n배 한 결과를 표시하는 `TimesTable structure`를 선언하기 을 위한 읽기 전용의 서브스크립트를 구현하는 예제가 하나 있습니다.
```
struct TimesTable {
let multiplier: Int
subscript(index: Int) -> Int {
return multiplier * index
}
}
let threeTimesTable = TimesTable(multiplier: 3)
println("six times three is \(threeTimesTable[6])")
// prints "six times three is 18"
```
이 예제에서 새로운 `TimesTable`의 인스턴스는 3의 배수를 출력을 하도록 생성되고.
이것은 넘겨준 값인 3을 구조체의 `initializer`가 인스턴스의 `multiplier` 파라미터로 사용한 것을 의미합니다.
해당 서브스크립트를 부르는 것으로 `threeTimesTable`의 인스턴스에게 요청할 수 있다. 보는 바와같이 `threeTimesTable[6]`과 같이 부르는 것으로 `threeTimesTable` 인스턴스의 서브스크립트를 부를 수 있다. 해당 요청은 6의 3배 테이블을 요청했으며 그 값은 18=6*3 이 된다.

>NOTE
n배 테이블은 고정된 숫자값을 출력하는 규칙에 기반합니다. 따라서 **`newValue**`등을 통하여 **`treeTimesTable[someindex]**`를 따로 설정하는 것은 적절하지 않으며 그러기에 위의 **`TimesTable**`을 위한 서브스크립트는 읽기전용의 서브스크립트로 선언되었습니다.

## 서브스크립트 사용(Subscript Usage)

아주 정확한 의미의 "subscript"는 그것이 사용되는 문맥에 따라 결정된다. 서브스크립트는 일반적으로 collection, list, 또는 sequence에 특정 member elements에 접근하기 위한 단축형이라는 의미로 사용되며, 당신은 특별한 클래스나 구조체의 기능을 위해 적절한 방식으로 자유롭게 대부분의 서브스크립트를 구현할 수있다.
예를 들어서 Swift의 `Dictionary` 타입은 `Dictionary` 인스턴스에 저장된 값들을 설정하고 검색하기 위한 하나의 서브스크립트로 구현했다.
당신은 딕셔너리 안에 딕셔너리의 키의 타입의 키값을 서브스크립트의 '[]'안에 넣는 것으로 값을 세팅할 수 있으며 딕셔너리 안에 들어갈 값을 서브스크립트에 할당할 수도 있다:
```
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2
```
위 예제는 `numberOfLegs`라는 변수를 선언하고 이를 3가지 key-value 쌍을 가진 딕셔너리 literal로 초기화 하고있다.
`numberOfLegs` 딕셔너리의 타입은 `Dictionary` 를 뜻하며. 딕셔너리가 생성이 된 후, 이 예제는 서브스크립트 assignment을 사용하여 `String` 키인 `"bird"`와 `Int` 값인 2를 딕셔너리에 추가하는 것을 볼 수있다.
딕셔너리 서브스크립트에 관한 보다 많은 정보를 원한다면, [Accessing and Modifying a Dicionary](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_142)를 참고하기 바란다.

>NOTE
Swift의 딕셔너리 타입은 내부적인 key-value 서브스크립트가 요구하고 반환하는 타입이 옵셔널 타입인 서브스크립트로 구현하였습니다. 위에서 **`numberOfLegs**` 딕셔너리를 보면, key-value 서브스크립트를 요구하고 반환하는 타입이 `Int`일까요?, 그렇지 않으면 옵셔널 `Int`일까요? 딕셔너리 타입은 '모든 키가 값을 가지는 것은 아니다'라는 사실을 위한 모델을 지원하기 위해 옵셔널 서브스크립트 타입을 사용합니다. 그리고 어떤 키에 값을 삭제하는 방법을 제공하는데, 이 경우 해당 키값의 값는 `nil`로 할당된다.

## 서브스크립트 옵션(Subscript Options)

서브스크립트는 어떠한 숫자의 입력 파라미터들도 처리가 가능하다.그리고 그리고 이 입력 파라미터들은 어떠한 타입도 가능하다. 서브스크립트는 또한 어떠한 타입으로도 리턴이 가능하다. 서브스크립트는 변수 파라미터와 variadic parameters도 가능하지만, in-out parameters 나 default parameter 값은 지원하지 않습니다.
클래스나 구조체는 필요한 만큼의 서브스크립트를 구현하는 것이 가능하며, 적절한 서브스크립트는 보통 각각의 서브스크립트가 사용되는 요소요소에서 서브스크립트에 포함되어 서로 대비하도록 한 값이나 값들의 타입이 기초라고 생각할 수 있습니다.
이러한 다수의 서브스크립트에 관한 정의는 _서브스크립트 overloading_으로도 알려져 있습니다.
대부분의 한개의 파라미터만을 요구하는 서브스크립트와는 다르게, 만일 당신이 만들 것에 필요하다면, 다수의 파라미터를 요구하는 서브스크립트를 선언할 수도 있습니다.
다음 예제는 `Double`값을 가지는 2차원 행렬을 표현하는 `Matrix`라는 구조체를 선언하고 있습니다. `Matrix` 구조체의 서브스크립트는 두개의 정수형 파라미터를 요구 하고 있습니다:
```
struct Matrix {
let rows: Int, columns: Int
var grid: Double[]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
grid = Array(count: rows * columns, repeatedValue: 0.0)
}
func indexIsValidForRow(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
subscript(row: Int, column: Int) -> Double {
get {
assert(indexIsValidForRow(row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
set {
}
set {
assert(indexIsValidForRow(row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
}
}
```
`Matrix`는 `rows`와 `columns`이라는 두개의 파라미터를 요구하는 initializer 를 제공하며, `Double` 타입으로 `rows * columns`를 충분히 저장할 수 있을만큼 큰 배열을 생성합니다. 각 `Matrix`의 위치의 초기값은 `0.0`으로 주어지며. 이러한 작업이 모두 이루어 진 다음에는 만들어진 배열을 배열의 initializer로 보내서 올바른 크기의 배열을 만듭니다. 이 initializer에 다한 자세한 사항은 [Creating and Initializing an Array](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_142)를 참고하세요.

이제 다음과 같은 방식으로 적절한 row와 column을 initializer에 넘기는 것으로 새로운 `Matrix` 인스턴스를 생성할 수 있습니다.
```
var matrix = Matrix(rows: 2, columns: 2)
```
아래의 예제는 2x2의 크기를 가진 새로운 `Matrix` 인스턴스를 생성하는 예제입니다. `Matrix` 인스턴스를 효과적이도록 평평하게 펴서 보여주기 위한 `grid` 배열을 참고하면 왼쪽위에서부터 오른쪽 아래로 읽어 나가는 것을 볼 수 있습니다.

![](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/subscriptMatrix01_2x.png)

`matrix`에 값을 넣을때는 row,column를 이용해서 서브스크립트에 맞는 형태로 값을 넘겨주면 설정할 수 있습니다:
```
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2
```
이 두 문장은 우측 상단의 값([0, 1])을 `1.5`로, 좌측 하단의 값([1, 0])을 `3.2`로 설정합니다:

![](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/subscriptMatrix02_2x.png)

`Matrix`의 서브스크립트의 getter와 setter는 모두 올바른 `row`와 `column`값이 들어오는지 체크하는 assertion을 포함하고 있습니다. 이 assertion들을 돕기 위하여 `Matrix`는 자체적으로 `indexIsValid`라는 convenience method를 가지고 있으며 이는 주어진 값이 `matrix`의 범위를 넘어가는지 아닌지를 체크합니다:
```
func indexIsValidForRow(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
```
만일 `matrix`의 경계를 넘어가는 값이 서브스크립트로 들어오게 된다면 assertion이 발생합니다:
```
let someValue = matrix[2, 2]
// this triggers an assert, because [2, 2] is outside of the matrix bounds
```


chapter20
# 20 타입 변환 (Type Casting)
> Translator : Snowcat8436 (snowcat8436@gmail.com)

## 타입변환(Type Casting)

타입 변환이란 인스턴스(instance)의 타입을 체크하기 위한 방법이며, 또한 이것은 인스턴스를 마치 해당 클래스가 가친 계층구조에서 온 상위클래스나 하위클래스처럼 다룬다.
Swift에서 타입 변환은 `is`와 `as`라는 연산자로 구현할 수 있으며, 이 두 연산자는 값의 타입을 체크하거나 다른 타입으로 변환하는 간단하고 표현적인 방법을 제공합니다.
또한 해당 타입이 프로토콜에 적합하지 아닌지 체크하기 위해서 타입 변환을 사용할 수 있으며 보다 자세한 사항은 [Protocol Conformance](링크)를 참조하시기 바랍니다.

## 타입 캐스팅을 위한 클래스 계층 정의(Defining a Class Hierarchy for Type Casting)

당신은 특정한 클래스의 인스턴스의 타입을 체크하거나 인스턴스를 같은 계층의 또다른 클래스로 변환하기 위해서 클래스들과 하위클래스들의 계층정보를 사용한 타입캐스팅을 할 수 있다.
아래의 세가지의 코드조각(code snippets)는 타입 캐스팅이 사용되는 예제를 보여주기 위한 계층적인 클래스들과 각각의 클래스들의 인스턴스를 포함하는 배열(array)를 정의하고 있습니다.
첫번째 코드 조각은 `MediaItem`이라는 새로운 기본 클래스(base class)를 정의하고 있습니다. 이 클래스는 디지털 미디어 라이브러리에 있는 모든 아이템들을 위한 기본적인 기능을 제공합니다. 특히 문자열(`String)` 타입의 `name` 속성(Property)를 선언하고, `init name` initializer를 통해서 'name'을 초기화 합니다(이것은 모든 미디어 아이템(영화나 노래)들이 이름을 가지고 있다고 가정합니다)

```c
class MediaItem {
var name: String
init(name: String) {
self.name = name
}
}
```

다음 코드 조각은 `MediaItem`의 두가지 하위클래스(subclasses)들입니다. 첫번째 하위클래스인 `Moive`는 내부적으로 영화에 관한 추가적인 데이터를 가지고 있는데. 이는 '`director'`라는 속성 및 초기화 부분을 `MediaItem`클래스의 initalizer의 윗부분에 추가하는것으로 더할 수 있으며. 두번째 하위 클래스인 '`Song'``artist` 속성의 관한 내용을 선언하고 base class의 윗부분에서 이를 초기화 한다:
```c
class Movie: MediaItem {
var director: String
init(name: String, director: String) {
self.director = director
super.init(name: name)
}
}

class Song: MediaItem {
var artist: String
init(name: String, artist: String) {
self.artist = artist
super.init(name: name)
}
}
```
마지막 코드조각은 2개의 `Movie` 인스탄스와 3개의 `Song` 인스턴스를 포함하는 `library`로 불리는 상수형 배열(constant array)를 만든다.
`library` 배열의 타입은 각각의 배열 내부의 콘텐츠를 초기화 하는 타입으로 추정할 수 있다.
Swift의 타입 체커는 `Movie``Song`이 공통의 상위 클래스(superclass)인 `MediaItem`을 가진다고 추정할 수 있고, 따라서 `library`의 타입은 `MediaItem[]`로 추정할 수 있다 :
```c
let library = [
Movie(name: "Casablanca", director: "Michael Curtiz"),
Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
Movie(name: "Citizen Kane", director: "Orson Welles"),
Song(name: "The One And Only", artist: "Chesney Hawkes"),
Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
]
// the type of "library" is inferred to be MediaItem[]
```
`library`에 저장된 요소들은 해당 Scenes뒤에서는 여전히 `Movie``Song`인스탄스이다. 그러나 만일 네가 이 array의 컨텐츠들을 반복자 등을 이용하여 뽑아낸 다면, 네가 받게된 그 아이템들의 타입은 Song이나 Movie이 아닌 MediaItem일 것이다. 그것들을 원래의 타입으로 작업을 하기 위해얻고 싶다면, 당신은 그들의 타입을 체크하는 것이 필요하고, 또한 그들을 다운캐스트해서 다른 타입으로 변경하여야 한다. 이는 아래서 설명하도록 하겠다.

## 타입 체크(Checking Type)

어떠한 인스턴스가 확실히 하위클래스 타입인지 아닌지를 체크하기 위해서는 타입 체크 연산자인 `is`를 이용합니다. 이 타입체크용 연산자는 만일 해당 인스탄스가 해당 하위 클래스라면 `true`를, 아니라면 `false`를 반환합니다.
아래의 예시는 `library` 배열에 있는 `Movie`의 인스턴스의 수와 `Song`의 인스턴스의 수를 세기 위한 `movieCount``songCount`라는 두개의 변수를 선언하는 것을 보여줍니다.:
```c
var movieCount = 0
var songCount = 0

for item in library {
if item is Movie {
++movieCount
} else if item is Song {
++songCount
}
println("Media library contains \(movieCount) movies and \(songCount) songs")
// prints "Media library contains 2 movies and 3 songs"
```
이 예시에서는 `library`배열의 모든 아이템에 대해서 작업하며, 각각의 1번의 과정마다 `for-in loop` 루프는 배열에 `MediaItem` 상수를 가져오고, 옵니다.
각각의 아이템이 만일 `Movie` 인스탄스이면 `item is Movie`에서 `true`를 아니라면 `false`를 반환하고, 이와 유시하게 아이템이 만일 Song의 인스탄스인지 아닌지에 따라 `item is Song` 체크부분의 리턴값이 결정됩니다. `for-in loop` 루프의 마지막이 되면, `moveCount``songCount`의 값을 보고 전체 `MediaItem` 인스탄스중에 각각의 타입이 얼마만큼의 수가 들어있는지 찾아낼 수 있다.

## 다운캐스팅( Downcasting )

상수와 변수의 명확한 클래스 타입은 사실은 아마도 the scenes뒤에 있는 하위 클래스의 인스탄스에 속할것이다.
당신이 위와 같은 케이스를 믿는 경우, 당신은 타입 변환 연산자인 '`as'`를 통하여 하위클래스타입으로 다운캐스팅을 시도 할 수 있다.
다운캐스팅은 실패할 수 있기때문에, 타입 캐스팅연산자는 두가지의 다른 형태를 가집니다.
하나는 `as?`와 같은 연산자를 사용하는 optional form으로 다운캐스팅을 시도하여 optional value를 리턴합니다.
다른 하나는 `as`와 같은 연산자를 사용하는 forced form으로 다운 캐스팅을 시도하고 강제로 unwrap한 결과를 한번에 합한 작업을 합니다.
네가 만일 다운캐스트가 성공할지 확신을 가지지 못한다면 타입변환 연산자인 `as?`를 이용하는 optional form을 사용한다. 위 연산자를 사용하는 form은 항상 optional value를 리턴하며 그래서 만일 다운 캐스트가 가능하지 않은 경우에는 `nil`을 리턴할 수 있도록 할 수 있다. 이 것은 당신이 다운 캐스팅의 성공 유무를 체크할 수 있도록 하게 한다.
오직 당신이 다운캐스트가 항상 성공할 것이라는 확신이 있다면 타입 변환 연산자인 `as`를 이용하는 forced form을 사용할 수 있다. 위의 연산자를 사용하는 form은 만일 올바르지 않은 클래스 타입으로 다운캐스팅을 시도했을 시에 런타임 에러를 발생시킨다.
아래에 `library` 내의 각 `MediaItem`을 반복해가면서 각 아이템들을 위한 적절한 설명을 출력하는 예시를 만들었다. 이를 위해서 각 아이템이 단순히 `MediaItme`이 아닌 진정으로 `Movie``Song`인지 억세스 해볼 필요가 있다. 이를 위해서 설명을 출력하기 위해서 `Movie``Song``director``artist` 속성에 접근할수 있게 할 필요가 있다.
예시에서 배열내의 각각의 item은 `Movie`이거나 `Song`이라고 생각된다. 당신은 각각의 아이템이 실제 어떠한 클래스인지 미리 알 수가 없습니다. 그러므로 optional form을 위한 `as?` 연산자를 사용하여 루프를 통해 각 케이스마다 다운캐스팅을 체크하는 것이 적절합니다:
```c
for item in library {
if let movie = item as? Movie {
println("Movie: '\(movie.name)', dir. \(movie.director)")
} else if let song = item as? Song {
println("Song: '\(song.name)', by \(song.artist)")
}
}

// Movie: 'Casablanca', dir. Michael Curtiz
// Song: 'Blue Suede Shoes', by Elvis Presley
// Movie: 'Citizen Kane', dir. Orson Welles
// Song: 'The One And Only', by Chesney Hawkes
// Song: 'Never Gonna Give You Up', by Rick Astley
```
이 예시는 현재 아이템이 `Movie`라고 생각하고 다운 캐스팅을 시도하는 것으로 시작합니다. 아이템이 `MediaItem` 인스탄스이므로 이 아이템은 `Movie`일 수 있습니다, 또한 똑같은 이유로 `Song`도 가능합니다, 혹은 오로지 단순히 `MediaItem`일수도 있습니다. 이것이 불확실 하기 때문에, `as?` 타입변환 연산자를 사용하여 하위 클래스로의 다운캐스팅을 시도시에 optional value를 반환합니다. 그 결과 `item as Moive`의 결과는 `Move?` 타입, 즉 optional `Movie`이 됩니다.
`library` 배열안의 두개의 `Song` 인스탄스에 해당 내용을 적용하여 `Movie`로 다운캐스팅을 할경우 실패한다. 이것에 대처하기 위해, 위의 예시에서는 결과로 나온 optional `Movie`값이 실제로 값을 가지고 있는지 체크하기 위한(이 경우는 다운캐스팅이 성공했는지 아닌지 찾는 과정이다) optional binding을 사용한다.
이 optional binding 은 "`if let movie = is as? Moive"`와 같이 적히며, 이는 다음과 같이 해석될 수 있다: "해당 아이템을 `Movie`로 생각하고 접근을 시도한다. 만일 해당 작업이 상공하면, 반환된 optional `Movie`값을 저장할 `movie`라고 불리는 새로운 임시 상수값을 설정한다.
만일 다운 캐스팅이 성공한다면, `movie`의 속성들을 가지고 `director`와 같은 `Moive` 인스탄스를 위한 설명을 출력하는데 사용할 수 있습니다.
비슷한 원리로 `Song` 인스턴스를 위한 체크를 하여, `library`에서 `Song` 인스탄스를 찾기만 한다면, `artist`와 같은 적절한 설명을 출력할 수 있습니다.

>NOTE
변환(Casting)은 실제로 해당 인스턴스를 수정하거나 그 값을 바꾸는 것이 아닙니다. 근본적인 인스턴스는 처음상태 그대로 남아있습니다. 이것은 간단히 특별한 것이며, 캐스팅된 타입의 인스턴스로서 접근이 가능한 것입니다.

## Type Casting for Any and AnyObject

Swift는 특정한 타입을 가지지 않는 상태로 작업하기 위한 두가지의 특별한 타입을 제공합니다:

`AnyObject`는 어떠한 클래스타입의 인스턴스라도 표현할 수 있습니다
`Any`는 함수형의 타입을 제외하고는 어떠한 타입의 인스턴스라도 표현할 수 있습니다.

>NOTE
`Any`나 `AnyObject`는 오로지 당신이 명시적으로 behavior나 그들이 제공하는 능력들이 필요한 경우에만 사용합니다. 이는 항상 당신의 코드 속에서당신이 예상한 특정한 형태의 타입으로 작동하는 것이 더 낫습니다.

## AnyObject

Cocoa APIS를 이용하여 작업을 할때, 보통 `AnyObject`[] 타입의 배열을(`AnyObject` 타입의 값을 가진 배열) 받는것이 일반적입니다. 이것은 Objective-C가 명시적인 타입의 배열을 가지지 못하기 때문입니다. 그러나 당신이 종종 당신이 알고있는 API가 제공하는 배열을 포함한 여러가지 정보를 포함한 오브젝트들의 타입에 대해서 자신이 있을 수 있다.
이러한 상황에서, 당신은 optional unwrapping이 필요하지 않은 경우에 한하여 배열의 각각의 아이템을 특정한 클래스의 타입으로 바꾸는 다운캐스팅을하기 위한 타입 변환 연산자 `as`로 강제로 변경한 형태를 사용할 수 있습니다.
```
let someObjects: AnyObject[] = [
Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"),
Movie(name: "Moon", director: "Duncan Jones"),
Movie(name: "Alien", director: "Ridley Scott")
]
```
이 배열은 오로지 `Moive` 인스턴스만 가지는 것을 이미 알고 있으므로, 당신은 다운캐스팅 및 타입 변환 연산자 `as`를 이용하여 non-optional `Moive`로 강제로 형태를 바꾸는 unwrap를 할 수 있습니다.
```c
for object in someObjects {
let movie = object as Movie
println("Movie: '\(movie.name)', dir. \(movie.director)")
}
// Movie: '2001: A Space Odyssey', dir. Stanley Kubrick
// Movie: 'Moon', dir. Duncan Jones
// Movie: 'Alien', dir. Ridley Scott
```
루프를 조금더 짧게 만들기 위해서, 각 아이템을 다운캐스팅하는 대신에 `someObjects` 배열을 `Movie[]` 타입으로 다운 캐스팅 할 수도 있습니다:
```c
for movie in someObjects as Movie[] {
println("Movie: '\(movie.name)', dir. \(movie.director)")
}
// Movie: '2001: A Space Odyssey', dir. Stanley Kubrick
// Movie: 'Moon', dir. Duncan Jones// Movie: 'Alien', dir. Ridley Scott
```

## Any

이곳에 non-class타입을 포함한 여러가지 다른 타입을 섞어서 작업하기 위한 `Any`를 사용한 예제가 있다. 이 예제는 `Any`타입의 값을 저장할 수 있는 `things`이라는 한 배열을 생성한다.
```c
var things = Any[]()

things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append((3.0, 5.0))
things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
```
`things`배열은 두개의 `int` 값, 두개의 `Double`값, 하나의 `String`값, 하나의 (`Double`,`Double`)타입의 tuple, 그리고 "Ghostbusters"의 name과 "Ivan Retiman"의 director속성을 가진 Moive를 한개 가지고 있다.
당신은 `Any`나 `AnyObject`로 알고있는 변수에서 특정한 타입의 상수나 변수 찾기 위한 스위치 구문의 `case` 항목에 `is`와 `as` 연산자를 사용할수 있습니다.
아래의 예제는 아이템들의 `things` 배열의 각 아이템을 반복하면서 스위치 문을 통해서 각각의 타입을 요청한다.
몇몇의 `switch`문의 `case`항목에서 비교항목과 동일한 값과 타입을 가지는 상수의 경우는 해당 값과 형태를 출력한다:
```
for thing in things {
switch thing {
case 0 as Int:
println("zero as an Int")
case 0 as Double:
println("zero as a Double")
case let someInt as Int:
println("an integer value of \(someInt)")
case let someDouble as Double where someDouble > 0:
println("a positive double value of \(someDouble)")
case is Double:
println("some other double value that I don't want to print")
case let someString as String:
println("a string value of \"\(someString)\"")
case let (x, y) as (Double, Double):
println("an (x, y) point at \(x), \(y)")
case let movie as Movie:
println("a movie called '\(movie.name)', dir. \(movie.director)")
default:
println("something else")
}
}

// zero as an Int
// zero as a Double
// an integer value of 42
// a positive double value of 3.14159
// a string value of "hello"
// an (x, y) point at 3.0, 5.0
// a movie called 'Ghostbusters', dir. Ivan Reitman
```

>NOTE
`switch`문의 `case`항목들은 체크 및 특정한 타입으로의 변환을 위해서 `as`나 `as?`를 통해서 강제로 변경된 형태를 사용한다. 이런 체크는 `switch`문의 문맥안에 있는 이상 항상 안전하다.
chapter21
# 21 중첩 타입 (Nested Types )
> Translator : Alice Kim (mail@jua.kim)

열거형(Enumerations)은 종종 특정 클래스 또는 구조체(structure)의 기능을 지원하기 위해 만들어집니다. 마찬가지로, 복잡한 형태의 맥락에서 사용하기위한 유틸리티 클래스 또는 구조체를 정의하는데 유용합니다. 이를 위해 Swift는 중첩을 지원하는타입의 정의 안에 열거형, 클래스, 구조체를 내장타입으로 사용할 수 있게 함[^1]으로써 **중첩타입(Nested Types)**을 정의 할 수있습니다.
[^1]>역자 주:
예를 들면, 구조체 안에 클래스를 정의하고 그 클래스 안에 다시 열거형 또는 사용자가 정의한 구조체를 넣을 수있다는 얘기.

기존 타입안에 새로운 타입을 중첩하기 위해서는, 기존 타입이 둘러싸고 있는 중괄호('{','}'`{`,`}`) 안에서 정의를 작성합니다. 이러한 유형은 필요로 하는 만큼 여러 수준으로 중첩 될 수 있습니다.

## Nested Types in Action
아래의 예제에서는 블랙잭 게임에서 사용되는 게임 카드를 모델로 하는 `BlackjackCard`구조체를 정의하고 있습니다. `BlakcJack` 구조체는 내부에 `Suit`와 `Rank` 라는 이름의 두개의 열거형 타입을 가지고 있습니다.

블랙잭 게임에서 에이스 카드는 1또는 11의 값을 가지고 있습니다. 이러한 요소는 `Values`라는 구조체에 의해 표현됩니다. `Values` 구조체는 `Rank` 열거형 내부에 중첩되어 있습니다.

```
struct BlackjackCard {
// nested Suit enumeration
enum Suit: Character {
case Spades = "♠", Hearts = "♡", Diamonds = "♢", Clubs = "♣"
}

// nested Rank enumeration
enum Rank: Int {
case Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King, Ace
struct Values {
let first: Int, second: Int?
}
var values: Values {
switch self {
case .Ace:
return Values(first: 1, second: 11)
case .Jack, .Queen, .King:
return Values(first: 10, second: nil)
default:
return Values(first: self.toRaw(), second: nil)
}
}
}

// BlackjackCard properties and methods
let rank: Rank, suit: Suit
var description: String {
var output = "suit is \(suit.toRaw()),"
output += " value is \(rank.values.first)"
if let second = rank.values.second {
output += " or \(second)"
}
return output
}
}
```

`Suit`열거형은 4가지 슈트[^2]들과 슈트의 그에 해당하는 `Character` 심볼 값을 함께 나타냅니다.
[^2]: >역자 주:
블랙잭에서 슈트란 카드에 있는 무늬를 말합니다.

`Rank` 열거형은 13가지 카드의 랭크와 그에 해당하는 `Int` 값을 나타냅니다. (`Int`형의 숫자 값은 Jack, Queen, King, Ace 카드에는 사용되지 않습니다.)

위의 코드를 보면 알 수 있듯이, `Rank` 열거형은 `Values`라는 추가적인 구조체를 포함하는 중첩구조의 형태를 취하고 있습니다. 이 구조는 대부분의 카드는 하나의 값을 가지지만, 에이스 카드는 두가지 값을 갖는다는 사실을 캡슐화합니다.`Values` 구조체는 다음과 표현하는 두가지 속성을 정의하고 있습니다.
- `Int` 형의 **`first**`
- `Int?` 형 또는 **`optional Int**` 형의 **`second**`

`Rank`도 `Values`구조체의 인스턴스를 반환하는 계산된 **`values**` 속성을 정의합니다. 이 계산된 속성은 카드의 순위를 고려하여 그 순위에 따라 적절한 값을 가지는 새로운 `Values`인스턴스를 초기화 합니다. 이러한 속성은 `Jack`, `Queen`, `King`, `Ace` 과 같은 특별한 값을 위해 사용합니다. 숫자카드의 경우에는 지정되어 있는 `Int` 값을 사용합니다.

`BlackjackCard` 구조체는 **`rank**와 **`와 `suit**`라는 두개의 속성을 가지고 있고, **`description**`이라는 계산된 속성도 정의하고 있습니다. 이 **`description**` 속성은 카드의 이름과 값에 대한 설명을 빌드하기 위해 **`rank**와 **`와 `suit**`에 저장된 값을 사용합니다.

`BalckjackCard`구조체는 커스텀 이니셜라이저를 가지고 있지 않으므로, 앞 챕터의 [구조체 타입을 위한 멤버 단위의 이니셜라이저(Memberwise Initializers for Structure Types)](Intialization 챕터 쪽 링크필요)에서 설명한대로 암시적인 멤버단위 이니셜라이저(memberwise intializer)를 가지고 있습니다.

```
let theAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades)
println("theAceOfSpades: \(theAceOfSpades.description)")
// prints "theAceOfSpades: suit is ♠, value is 1 or 11
```

`Rank`와 `Suit`가 `BlackjackCard`안에 중첩되어 있다고 해도 그들의 타입은 문맥으로 부터 추론될 수 았가 때문에 이 인스턴스의 초기화는 자신의 맴버 이름(`.Ace``.Spades`)으로 열거형 멤버를 참조할 수 있습니다. 위의 예에서는 **`description**` 속성이 올바르게 Space Ace 카드가 1`1` 또는 `11`의 값을 가지고 있는지 확인합니다.

## 중첩 타입 참조하기 (Referring to Nested Types)
자신이 정의된 문맥 외부에서 중첩타입을 사용하려면, 자기를 포함하고 있는(중첩하고 있는)타입의 이름을 그 이름앞에 붙입니다.

```
let heartsSymbol = BlackjackCard.Suit.Hearts.toRaw()
// heartsSymbol is "♡"
```

위의 예를 보면, `Suit`, `Rank`, `Values`와 같은 이름들은 자연스럽게 그들이 정의된 문맥에 의해 규정되기 때문에 의도적으로 짧게 유지할 수 있습니다.
chapter22
# 22 확장 (Extensions)
> Translator : Dongwoo Son (easthelper@gmail.com)

확장(Extensions)은 이미 존재하는 클래스, 구조체, 열거형 타입에 새 기능성을 추가합니다. 이는 원본 소스코드에 접근할 수 없는 타입들도 확장할 수 있습니다. (Retroactive modeling) 확장은 Objective-c 의 카테고리 와 유사합니다.

Swift 의 확장이 할수있는 것:

* computed properties, computed static properties의 추가
* 인스턴스 메소드와 타입 메소드 정의
* 새로운 이니셜라이저 제공
* 서브스크립트 정의
* 기존 타입에 프로토콜 적용시키기

> 주의NOTE
만약 기존 타입에 새로운 기능성을 추가하기 위해 확장을 정의 한다면, 확장이 정의 되기 이전에 생성된 해당 타입의 모든 인스턴스들도 새 기능성이 적용이 됩니다.

## 확장 문법
`extension` 키워드로 확장을 선언합니다:
```
extension SomeType {
// SomeType에 추가할 새 기능
}
```
확장은 기존의 타입을 하나 이상의 프로토콜을 적용하기 위해서 확장시킬 수 있습니다. 이 경우 클래스 또는 구조체와 같은 방식으로 적용시킬 프로토콜 이름을 적습니다:
```
extension SomeType: SomeProtocol, AnotherProtocol {
// 프로토콜의 요구사항을 이곳에 구현
}
```
확장으로 프로토콜 준수의 추가는 [Adding Protocol Conformance with an Extension]() 에 설명 되어 있습니다.

## 연산 속성
확장은 연산 인스턴스 속성과 연산 타입 속성을 기존의 타입에 추가할 수 있습니다. 이 예제는 거리 단위를 제공하기 위해 다섯개의 연산 인스턴스 속성을 Swift의 내장 `Double` 타입에 추가합니다.
```c
extension Double {
var km: Double { return self * 1_000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
println("One inch is \(oneInch) meters")
// prints "One inch is 0.0254 meters"
let threeFeet = 3.ft
println("Three feet is \(threeFeet) meters")
// prints "Three feet is 0.914399970739201 meters"
```
이러한 연산 속성들은 `Double` 값이 특정 길이의 단위로 간주됨을 나타냅니다. 연산 속성들로 구현되었지만 부동소수점 리터럴 값에 점 문법으로 속성의 이름을 덧붙여 리터럴 값을 거리값으로 변환시킬 수 있습니다.

예를들어, `1.0`이라는 `Double` 값은 "1 미터"로 간주됩니다. 때문에 `m` 연산 속성은 `self` 를 반환합니다. - `1.m` 표현은 `1.0` `Double` 값 입니다.

다른 단위들은 미터 측정값으로 표현되기 위한 변환이 필요합니다. 1 킬로미터는 1000 미터와 같습니다. 따라서 `km` 연산 속성은 미터로 표현되기 위해 `1_000.00` 을 곱합니다. 같은 방식으로 1 미터는 3.28024 피트입니다. 따라서 피트를 미터로 바꾸기 위해 `ft` 연산 속성은 `double` 값을 `3.28024` 로 나눕니다.

이 속성들은 읽기 전용 속성이고 간결함을 위해 `get` 키워드 없이 사용될 수 있습니다. 속성들의 반환 값은 `Double` 형이기 때문에 `Double` 을 사용하는 어느 곳에서나 수학적 계산과 함께 사용 될 수 있습니다.

```
let aMarathon = 42.km + 195.m
println("A marathon is \(aMarathon) meters long")
// prints "A marathon is 42195.0 meters long"
```

> 주의NOTE
확장은 새로운 연산속성을 추가할 수 있습니다. 하지만 저장 속성 또는 기존 속성에 프로퍼티 옵저버를 추가할 수는 없습니다.

## 이니셜라이저
확장은 기존 타입에 새로운 이니셜라이저를 추가할 수 있습니다. 이는 다른 타입들이 여러분의 커스텀 타입을 이니셜라이저의 인자로 받을 수 있도록 하거나 또는 타입의 기본 구현에 포함되어 있지 않은 추가 적인 이니셜라이저 옵션을 제공할 수 있도록 확장하는 것을 가능하게 합니다.

확장은 새 convenience 이니셜라이저를 클래스에 추가할 수 있습니다. 하지만 새 designated 이니셜라이저 또는 디이니셜라이저를 추가할 수는 없습니다. designated 이니셜라이저와 디이니셜라이저는 반드시 본래의 클래스 구현에서 제공되어야 합니다.

> 주의NOTE
만약 확장을 사용해서 모든 저장 속성의 기본 값을 제공하는 값 타입에 새로운 이니셜라이저를 추가하고, 어떠한 커스텀 이니셜라이저도 정의하지 않았다면, 기본 이니셜라이저와 memberwise 이니셜라이저를 호출 할 수 있습니다.
*[Initializer Delegation for Value Type*]()에서 설명한 것 처럼 이니셜라이저를 값 타입의 본래 구현에 작성을 한 경우에는 해당 되지 않습니다.

아래의 예제는 직사각형을 나타내기 위한 커스텀 `Rect` 구조체를 정의합니다. 또한 모든 속성의 기본값이 `0.0`인 `Size`와 `Point`구조체를 정의합니다.

```c
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
}
```

*[Default Initailizers*]() 에서 언급했던 것처럼 `Rect` 구조체는 모든 속성의 기본값을 제공하기 때문에 기본 이니셜라이저와 memberwise 이니셜라이저를 자동으로 받습니다. 이 이니셜라이저들은 새로운 `Rect` 인스턴스를 생성하기 위해 사용될 수 있습니다.

```c
let defaultRect = Rect()
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
size: Size(width: 5.0, height: 5.0))
```

`Rect` 구조체에 특정 중심점과 크기를 받기 위한 추가 이니셜라이저를 제공하기 위해 확장할 수 있습니다.
```
extension Rect {
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
```

이 새 이니셜라이저는 처음에 제공된 `center` 값과 `size`값을 기반으로 적절한 *origin point*를 계산합니다. 그 다음 구조체의 자동 memberwise 이니셜라이저 `init(origin:size:)`를 호출하여 새 origin 과 size 값을 적절한 속성에 저장합니다.

```c
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
size: Size(width: 3.0, height: 3.0))
// centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)
```

>주의NOTE
확장으로 새 이니셜라이저를 제공 할 경우 이니셜라이저가 완료되었을 때 각 인스턴스가 완전히 초기화 되었는지 확인하는 책임은 작성자에게 있습니다.

## 메소드
확장은 기존 타입에 새 인스턴스 메소드와 타입 메소드를 추가할 수 있습니다. 다음 예제는 새 인스턴스 메소드 `repetitions` 를 `Int` 타입에 추가합니다:
```
extension Int {
func repetitions(task: () -> ()) {
for i in 0..self {
task()
}
}
}
```
`repetitions` 메소드는 매개변수가 없고 반환 값이 없음을 나타내는 하나의 `()->()`인자를 받습니다.

이 확장을 정의한 후에 여러번의 반복작업을 위해 어느 정수값에서 `repetitions` 메소드를 호출 할 수 있습니다.

```c
3.repetitions({
println("Hello!")
})
// Hello!
// Hello!
// Hello!
```

호출을 더 간결하게 하기위해 후행 클로저 문법을 사용:
```
3.repetitions {
println("Goodbye!")
}
// Goodbye!
// Goodbye!
// Goodbye!
```

### Mutating 인스턴스 메소드
확장을 이용해 인스턴스 메소드 추가함으로써 인스턴스 스스로 또한 수정할 수 있습니다. `self` 또는 자신의 속성을 수정하는 구조체와 enumeration 메소드들은 반드시 인스턴스 메소드를 `mutating`으로 표시 해야합니다.

아래 예제는 원래의 값을 제곱하는 새 mutating 메소드 `square` 를 Swift의 `Int`타입에 추가합니다.

```
extension Int {
mutating func square() {
self = self * self
}
}
var someInt = 3
someInt.square()
// someInt is now 9
```

## Subscripts
확장은 기존 타입에 새 subscripts 를 추가할 수 있습니다. 이 예제는 integer subscript 를 Swift 내장 `Int` 타입에 추가합니다. 이 subscript `[n]` 는 수의 오른쪽으로 부터 `n`번째 자리에 있는 10진수 숫자 하나를 반환합니다:

* `123456789[0]` returns `9`
* `123456789[1]` returns `8`

... 기타 등등:

```
extension Int {
subscript(digitIndex: Int) -> Int {
var decimalBase = 1
for _ in 1...digitIndex {
decimalBase *= 10
}
return (self / decimalBase) % 10
}
}
746381295[0]
// returns 5
746381295[1]
// returns 9
746381295[2]
// returns 2
746381295[8]
// returns 7
```

만약 `Int` 값이 길이가 요구된 인덱스 보다 적다면 수 왼쪽이 0들로 채워져 있다 여기고 `0`을 반환합니다.

```
746381295[9]
// 다음을 요청한것 같이 처리되어 0 을 반환 합니다:
0746381295[9]
```

## Nested Types
확장은 새 Nested 타입을 기존 클래스, 구조체, enumeration에 추가할 수 있습니다.
```
extension Character {
enum Kind {
case Vowel, Consonant, Other
}
var kind: Kind {
switch String(self).lowercaseString {
case "a", "e", "i", "o", "u":
return .Vowel
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
return .Consonant
default:
return .Other
}
}
}
```
이 예제는 새 nested enumeration을 `Character`에 추가합니다. 이 `Kind` enumeration 은 각 문자의 종류를 나타냅니다. 특히 문자가 표준 로마자에서 모음 또는 자음인지(강세나 지역적 다양성을 고려하지 않고), 또는 그 외의 문자인지를 나타냅니다.

이 예제는 또한 새 연산 인스턴스 속성 `kind`을 `Character`에 추가합니다. 이 속성은 해당 문자에 적절한 `Kind` enumeration 멤버를 반환합니다.

이제 `Character` 값에서 nested enumeration 을 사용할 수 있습니다.

```
func printLetterKinds(word: String) {
println("'\(word)' is made up of the following kinds of letters:")
for character in word {
switch character.kind {
case .Vowel:
print("vowel ")
case .Consonant:
print("consonant ")
case .Other:
print("other ")
}
}
print("¶
")
}
printLetterKinds("Hello")
// 'Hello' is made up of the following kinds of letters:
// consonant vowel consonant consonant vowel
```

`printLetterinds` 함수는 `String` 값을 받아서 문자열의 각 문자를 iterate 합니다. 각 문자에 대해서 `kind` 연산 속성에 따라 그 글자에 알맞는 종류를 출력합니다. 위 "Hello" 단어의 결과 처럼 `printLetterinds` 함수를 호출해서 단어 안의 모든 문자의 종류들을 출력할 수 있습니다.

> 주의NOTE
`character.kind` 는 이미 `Character.Kind` 타입으로 알려져 있기 때문에 모든 `Character.Kind` 멤버 값들은 `switch` 문에서 `Character.Kind.Vowel`보다 `.Vowel`같이 생략된 형식으로 쓸 수 있습니다.