Merge changes from master into FlashMaestro

FlashMaestro authored
revision 240f9f3086db8c0cd8351b783f6d1f0fddf5250a
About
# Apple Swift Programming Language translation for KOREAN
**“Apple Inc. Copyright © 2014 Apple Inc. All rights reserved.”**
This is a [The Swift Programming Language](https://developer.apple.com/swift/) guide documentation translation project.

_This project is **never used for commercial purposes**.
By translating "The Swift Programming Language" we want to help a lot of korean learners who may otherwise struggle to understand it._

> 이 프로젝트는 애플의 새로운 프로그래밍 언어 **swift** 번역 프로젝트입니다. 자유롭게 참여하세요 =)
**이 번역 프로젝트는 절대로 상업적인 목적으로 사용되지 않습니다.**

## Original Contents
- [Download “The Swift Programming Language” from the iBooks Store](https://itunes.apple.com/us/book/the-swift-programming-language/id881256329?mt=11)
- [The Swift Programming Language 웹 사이트](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/)

## Let's translate it!
- 누가 어떤 챕터를 번역하고 있을까..? 저도 참여할 수 있을까요? - [번역작업 할당 현황](https://www.penflip.com/jjuakim/swift-korean/discussions/35)
- 번역을 시작하기전에 그리고 submit 하기 전에 꼭 읽어주세요! - [번역 가이드](https://www.penflip.com/jjuakim/swift-korean/discussions/36)
- 이러한 단어는 어떻게 번역해야 할까요? - [Dictionary](https://www.penflip.com/jjuakim/swift-korean/discussions/27)
chapter10
# 10 열거형 (Enumerations)
> Translator : inureyes (inureyes@gmail.com)

열거형 _(Enumeration)_ 은 관련있는 값들의 그룹에 대한 일반적인 타입을 정의하며, 이를 이용하여 코드 안에서 타입에 안전한 방법으로 작업할 수 있습니다. C에 익숙한 사용자라면, C 열거형은 관련있는 이름을 정수값의 set에 할당하는 것을 알고 있을 것입니다. Swift의 열거형은 훨씬 더 유연하며, 열거형의 각 숫자마다 반드시 값을 제공할 필요가 없습니다. 만약 ("원시(raw)" 값으로 알려진) 값이 각 열거형 번호마다 제공될 경우, 그 값들은 문자열, 글자, 어떠한 정수나 부동 소수점 타입이 될 수 있습니다.

또한, 열거형 멤버들은 각각 다른 멤버 값에 대하여 다른 언어의 union및 비슷한 기능들이 하듯 연관된 값들을 어떤 타입이든 지정할 수 있습니다. 관련있는 멤들의 일반적인 집합을 하나의 열거형의 부분으로 정의할 수도 있으며, 각각은 그에 연관된 적당한 타입의 값들의 다양한 집합을 가질 수 있습니다.

Swift의 열거형은 열거형의 현재 값에 대한 추가적인 정보를 제공하기 위한 계산된 프로퍼티나, 열거형이 표현하는 값들과 연관된 기능들을 제공하는 인스턴스 메소드 같이 전통적으로 클래스 등에서만 지원되는 많은 기능들을 차용하였습니다. 또한 열거형은 초기 멤버 값을 제공하는 initiailizer를 제공할 수 있고, 원래 구현을 넘어서 기능을 확장할 수도 있으며, 표준 기능을 제공하기 위한 프로토콜을 따를 수 있습니다.

이러한 기능에 대한 자세한 내용은 [속성](), [메소드](), [초기화](), [확장](), 및 [프로토콜]()을 참조하십시오.


### 열거형 문법 (Enumeration Syntax)
열거형은 `enum` 키워드로 작성하며, 중괄호 안에 모든 정의를 집어넣습니다.

enum SomeEnumeration {
// enumeration definition goes here
}
Here’s an example for the four main points of a compass:

enum CompassPoint {
case North
case South
case East
case West
}

(`North`, `South`, `East` 및 `West` 같이) 열거형에 정의된 값들은 이 열거형의 멤버 값들입니다. `case` 키워드는 멤버 값들의 새 줄이 정의될 것임을 나타냅니다.

> **노트**
> C 및 Objective-C 와는 다르게, Swift의 열거형 멤버들은 생성시 기본 정수값들에 할당되지 않습니다. 위의 `CompassPoints` 예제에서 보듯, `North`, `South`, `East` 및 `West`는 명시적으로 0, 1, 2 및 3에 대응되지 않습니다. 대신에, 기본 열거형 멤버들은 `CompassPoint`의 명시적으로 정의된 타입과 함께 정의된 완벽하게 갖춰진 값입니다.

여러 멤버 값들이 콤마(,) 로 구분되어 한 줄에 나올 수도 있습니다:

enum Planet {
case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}

각 열거형 정의들은 새로운 타입을 정의합니다. Swift의 다른 타입과 마찬가지로, 이름들 ( `CompassPoint` 및 `Planet`과 같은) 은 대문자로 시작해야 합니다. 열거형 타입에게 자명하게 읽힐 수 있도록 복수형 대신 단수형 이름을 주세요.

var directionToHead = CompassPoint.West

`directionToHead` 타입은 `CompassPoint`의 가능한 값들 중 하나가 초기화 될 때 유추됩니다. `directionToHead`가 `CompassPoint`로 선언되면, 짧은 닷 구문을 사용하여 그 값을 다른 `CompassPoint` 값으로 설정할당할 수 있습니다:

directionToHead = .East

`directionToHead`의 타입은 이미 알려져 있으므로, 값을 설정할당할 때 타입을 명기하지 않을 수 있습니다. 이러한 부분은 명시적으로 타입된 열거형 값들로 작업할 때 매우 읽기 편한 코드를 만들어줍니다.


## 열거형의 값들과 스위치 구문간의 대응 (Matching Enumeration Values with a Switch Statement)

각각의 열거형 값들을 `switch` 구문과 대응할 수 있습니다.

directionToHead = .South
switch directionToHead {
case .North:
println("Lots of planets have a north")
case .South:
println("Watch out for penguins")
case .East:
println("Where the sun rises")
case .West:
println("Where the skies are blue")
}
// prints "Watch out for penguins

이 코드는 다음과 같이 읽을 수 있습니다:
"`directionToHead`의 값을 봅시다. 만약 `.North`와 값이 같다면, `"Lots of planets have a north"` 를 출력합니다. 만약 `.South`와 값이 같다면, `"Watch out for penguins"` 를 출력합니다."

...식이 됩니다.

[제어 구문]() 에서 설명했듯이, `switch` 구문은 열거형 멤버를 고려할때 완벽하게 작성되어야 합니다. 만약 `.West`가 빠진 경우, 이 코드는 `CompassPoint` 멤버의 완벽한 리스트를 고려하지 않았기 때문에 컴파일되지 않을 것입니다. 완벽성 (exhaustiveness) 의 요구는 열거형 멤버가 실수로 생략되는 것을 방지합니다.

모든 열거형 멤버에 대한 케이스를 제공하기에 적당하지 않은 경우, 명시적으로 언급되지 않은 멤버들을 위한 기본 케이스를 제공할 수 있습니다.

let somePlanet = Planet.Earth
switch somePlanet {
case .Earth:
println("Mostly harmless")
default:
println("Not a safe place for humans")
}
// prints "Mostly harmless”

## 관련된 값들 (Associated Values)

앞 섹션의 에제는 열거형의 멤버들이 각각의 어떻게 정의되었는지 보여줍니다. 상수 및 변수를 `Planet.Earth` 에 설정할당할 수 있으며, 나중에 값들을 확인할 수도 있습니다. 그렇지만, 종종 멤버 값들과 함께 연관된 다른 타입의 값들을 저장하는 것이 유용한 경우들이 있습니다. 이는 추가적인 사용자 지정 정보를 멤버 값들마다 저장할수 있게 하며, 코드 안에서 멤버를 사용할 때 마다 정보가 변경되는 것을 허용합니다.

어떤 특정한 타입의 관련 값을 저장하는 Swift 열거형을 정의 할 수 있으며, 필요한 경우에 열거형의 각 멤에 따라 값의 형식은 다를 수 있습니다. 이러한 열거형과 유사한 경우들이 다른 언어에서는 차별된 공용체 (discriminated union), 태깅된 공용체 (tagged unions) 및 변형체 (variants) 로 알려져 있습니다.

예를 들어 재고 추적 시스템이 각 제품을 두가지 타입의 바코드로 추적할 필요가 있다고 해 봅시다. 어떤 제품들은 UPC-A 포맷의 0에서 9 사이의 숫자를 사용하는 1차원 바코드로 레이블링 되어 있습니다. 각 바코드는 열 개의 "확인 번호(identifier)" 숫자가 뒤따르는 "번호 시스템" 숫자를 갖고 있습니다. 이 숫자들 뒤에는 각 코드가 제대로 스캔되었는지를 검증하기 위한 "확인(check)" 숫자가 붙습니다.

![chapter10-fig1.png](images/chapter10-fig1.png)

다른 제품들은 모든 ISO 8859-1 문자를 사용할 수 있으며 2,953글자의 길이를 갖는 QR 코드 포맷의 2차원 바코드로 레이블링되어 있습니다.

![chapter10-fig2.png](images/chapter10-fig2.png)

재고추적 시스템이 UPC-A 바코드를 3개의 숫자 튜플로 저장하고, QR 코드는 임의의 길이의 문자열로 저장할 수 있다면 매우 편할 것입니다.

Swift에서, 각 유형의 제품의 바코드를 정의하는 열거형은 다음처럼 보일 것입니다:

enum Barcode {
case UPCA(Int, Int, Int)
case QRCode(String)
}

이 코드는 다음과 같이 읽을 수 있습니다:

"`(Int, Int, Int)` 타입의 UPCA 값 또는 `String` 타입의 QRCode 값을 가질 수 있는 `Barcode`라는 열거형 타입을 정의합니다."

이 정의는 어떠한 실제 `Int` 및 `String` 값을 제공하지 않습니다. 오직 바코드 상수 및 변수들이 `Barcode.UPCA` 또는 `Barcode.QRCode` 중 하나와 같을 때, 그와 연관된 값들의 타입만을 정의합니다.

이제 새 바코드는 두가지 타입 중 하나로 생성될 수 있습니다:

var productBarcode = Barcode.UPCA(8, 85909_51226, 3)

이 예제는 `productBarcode` 라는 새 변수를 생성하고, `Barcode.UPCA` 의 값으로 (8, 8590951226, 3) 튜플 값을 배정합니다. 제공된 "식별자" 값은 바코드로 읽기 좋도록 정수 표현 안의 밑줄 -85909_51226-로 을 갖고 있습니다.

동일한 제품이 다른 형태의 바코드로 배정될 수도 있습니다.

productBarcode = .QRCode("ABCDEFGHIJKLMNOP")”

이 경우, 원래 `Barcode.UPCA` 및 정수 값은 새로운 `Barcode.QRCode` 와 문자열 값으로 대체됩니다. `Barcode` 타입의 상수 및 변수들은 `.UPCA` 또는 `.QRCode` 중 하나를 (해당되는 값들과 함께) 저장할 수 있지만, 한번에 둘 중 하나만 저장할 수 있습니다.

서로 다른 바코드 타입들은 앞에서와 같이 스위치 구문을 사용하여 체크할 수 있습니다. 그러나, 이번 경우 관련된 값들은 스위치 구분의 일부로 추출될 수 있습니다. 각각의 연관 값들을 `switch`의 case 내용으로 사용하기 위하여 (`let` 접두사와 함께) 상수 또는 (`var` 접두사와 함께) 변수로 추출할 수 있습니다.

switch productBarcode {
case .UPCA(let numberSystem, let identifier, let check):
println("UPC-A with value of \(numberSystem), \(identifier), \(check).")
case .QRCode(let productCode):
println("QR code with value of \(productCode).")
}
// prints "QR code with value of ABCDEFGHIJKLMNOP."

만약 열거형 멤버들의 모든 연관 값들이 상수로 추출되었거나 모두 변수로 추출되었다면, 간결함을 위하여 멤버 이름 앞에 하나의 `var` 또는 `let` 을 붙일 수 있습니다:

switch productBarcode {
case let .UPCA(numberSystem, identifier, check):
println("UPC-A with value of \(numberSystem), \(identifier), \(check).")
case let .QRCode(productCode):
println("QR code with value of \(productCode).")
}
// prints "QR code with value of ABCDEFGHIJKLMNOP."

## 원시 값 (Raw Values)
연관값들을 사용한 바코드 예제는 어떻게 열거형의 멤버들이 그들이 저장하는 여러 타입의 관련된 값들을 선언하는지에 대해 보여주었습니다. 연관 값들에 대한 다른 방법으로, 열거형 멤버들은 (원시 값들이라고 부르는) 모두 같은 타입인 기본값들로 미리 채워질 수 있습니다.

아래는 원시 ASCII 값들을 이름붙은 열거형 멤버들에 저장하는 예입니다.

enum ASCIIControlCharacter: Character {
case Tab = "\t"
case LineFeed = "¶
"
case CarriageReturn = "\r"
}

여기서 `ASCIIControlCharacter` 열거형을 위한 원시 값들은 `Character` 타입이 되도록 정의되었으며, 더 일반적인 ASCII 제어 문자들로 할당되었습니다. `Character` 값들은 [문자열 및 글자]() 에 설명되어 있습니다.

원시 값들은 연관된 값들과 같지 않음을 유의하세요. 원시 값들은 위의 세가지 ASCII 코드들처럼 코드 안에서 처음 열거형을 정의할 때 미리 정의된 값들입니다. 개개의 열거형 멤버들의 원시 값은 언제나 동일합니다. 연관 값들은 새 상수 또는 변수를 열거형의 멤버 중 하나에 기초하여 생성할 때 할당되며, 무엇을 하느냐에 따라 매번 다를 수 있습니다.

원시 값은 문자열, 글자, 정수 또는 어떠한 부동 소수점 타입이 될 수 있습니다. 각각의 원시 값은 열거형 정의 안에서 반드시 유일해야 합니다. 원시 값으로 정수가 사용되었다면, 열거형 멤버의 일부에 아무 값도 설정되지 않은 경우 자동 증가(Auto-incrementation)할 것입니다.

아래의 열거형은 태양으로부터의 순서를 원시 정수값으로 표현하는 행성 열거형의 개선된 형태입니다.

enum Planet: Int {
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}

자동 증가는 `Planet.Venus`가 2의 원시 값을 갖는 식으로 진행되는 것을 의미합니다.


열거형 멤버의 원시 값들을 `toRaw` 메소드로 읽읍시다:

let earthsOrder = Planet.Earth.toRaw()
// earthsOrder is 3


열거형의 `fromRaw` 메소드를 사용하여 특정한 원시 값에 해당되는 열거형 멤버를 찾읍시다. 이 예제는 원시값 7에 해당되는 행성이 Uranus임을 판별합니다:

let possiblePlanet = Planet.fromRaw(7)
// possiblePlanet is of type Planet? and equals Planet.Uranus

모든 `Int` 값들이 해당되는 행성을 찾을 수 있는 것은 아닙니다. 그러므로, `fromRaw` 메소드는 추가적인 열거형 멤버를 반환합니다. 위의 예에서, `possiblePlanet` 은 `Planet?` 타입이거나 "optional `Planet`" 타입입니다.

만약 9번째 위치에 있는 행성을 찾는다면, `fromRaw`가 반환하는 추가적 `Planet` 값은 `nil` 이 될 것입니다:

let positionToFind = 9
if let somePlanet = Planet.fromRaw(positionToFind) {
switch somePlanet {
case .Earth:
println("Mostly harmless")
default:
println("Not a safe place for humans")
}
} else {
println("There isn't a planet at position \(positionToFind)")
}
// prints "There isn't a planet at position 9"

이 예제는 9의 원시값에 해당되는 행성을 읽기 위해 추가적인 바인딩을 사용합니다. `if let somePlanet = Planet.fromRaw(9)` 는 추가적인 `Planet`을 찾아내고, 찾을 수 있는 경우 추가적인 `Planet`의 내용을 `somePlanet`에 할당합니다. 이 경우, `9`의 위치에 있는 행성을 찾는 것은 불가능하기 때문에 `else` 브렌치가 대신 실행됩니다.

chapter19
# 19 옵션 연쇄 (Optional Chaining)
> Translator : 이름 (메일주소)

Write here...
허혁 (hyukhur@gmail.com)

선택 연쇄(Optional chaining)란 nil이 될 수 있는 선택지(options)를 가진 프로퍼티(property), 메소드(method), 서브 스크립트 (subscript)에 질의하고 호출하는 프로세스를 말한다. 만약 어떤 선택지가 값을 가진다면 프로퍼티, 메소드, 서브스크립트 호출은 성공하고 선택지가 nil이면, 프로퍼티, 메소드, 서브스크립트 호출은 nil을 반환하게 된다.
여러개의 질의도 함께 엮일 수 있으며, 만약 연쇄(chaining) 중간의 어떤 링크가 nil이라면 조용하게 전체 체인은 실패한다.

Note
스위프트(Swift)의 선택 연쇄가 오브젝티브씨(Objective-C)에 있는 nil에 메시지 보내기와 유사하다. 그러나, 모든 타입(any type)에서 동작하고, 성공, 실패 여부를 확인할 수 있다는 점에서 차이가 있다.

## 강제 랩핑 해제(Forced Unwrapping) 대안으로써 선택 연쇄
호출하고자 하는 프로퍼티, 메소드, 서브스크립트의 선택지 값(optional value)이 nil 아닐 때 선택지 값 뒤에 물음표(?)를 두어 선택 연쇄를 둘 수 있다. 이것은 선택지 값 뒤에 느낌표(!)를 두어 그 값을 강제로 랩핑 해제하는 것과 유사하다. 가장 주요한 차이점은 선택 연쇄는 선택지가 nil일 때 자연스럽게 실패한다는 것이고, 강제 랩핑 해제는 선택지가 nil인 경우 런타임 에러가 발생한다.
선택 연쇄가 nil 값에도 호출할 수 있다는 사실을 반영하기 위해 선택 연쇄 호출 결과는 항상 선택지 값이다. 비록 질의한 프로퍼티, 메소드, 서브스크립트가 항상 선택지 값이 아닌 결과를 도출해도 그렇다. 이 선택지 반환 값을 사용해서 선택 연쇄 호출이 성공했는지 ( 반환된 선택지가 값을 가지는 ) 연쇄 중간의 nil 값 ( 선택지 반환값이 nil ) 때문에 실패했는지를 확인할 수 있다.
구체적으로, 선택 연쇄 호출 결과는 선택지로 감싸여져 있음에도 기대한 반환값과 동일한 타입이다. 일반적으로 Int를 반환하는 프로퍼티는 선택 연쇄에 따라 접근이 가능할때는 Int?를 반환할 것이다.
다은 몇몇 코드 조각은 선택 연쇄가 어떻게 강제 랩핑 해제와 다르고 성공 여부 확인을 가능케 하는지 보여준다.
먼저 Person과 Residence 라는 클래스를 정의하자.
>class Person {
var residence: Residence?
}
>class Residence {
var numberOfRooms = 1
}

Residence 인스턴스(Instance)는 기본값이 1인 numberOfRooms 이라는 단 하나의 Int 프로퍼티를 가진다. Person 인스턴스는 Residence? 타입으로 residence 이라는 선택적 프로퍼티를 가진다.
만약 Person 이라는 인스턴스를 새로 만들면, 선택지가 된 효과에 따라 기본적으로 nil로 설정된다. 아래 코드에서는 john는 nil로 된 residence 프로퍼티를 가질 것이다.
let jone = Person()
만약 Person의 residence의 numberOfRooms 프로퍼티를 그 값을 강제로 랩핑 해제를 하려고 느낌표를 붙여서 접근한다면 런타임 에러(Runtime Error)를 유발시킬 것이다. 왜냐하면 해제할 residence 값 자체가 없기 때문이다.
let roomCount = john.residence.numberOfRooms
위 코드는 john.residence가 nil이 아닌 값을 성공하며 방 갯수에 적절한 숫자를 담고 있는 Int 값에 roomCount를 설정할 것이다. 그러나 이 코드는 위에 보여지는 것처럼 residence가 nil이라면 항상 런타임 에러를 유발 시킨다.
선택 연쇄는 numberOfRooms 값에 접근하는데 대안법을 제공한다. 선택 연쇄를 사용하기 위해 느낌표 자리에 물음표를 사용하면 된다.

>if let roomCount = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}
// prints "Unable to retrieve the number of rooms."

이것은 스위프트(swift)가 선택적 residence 프로퍼티를 "엮고" 만약 residence가 있으면 numberOfRooms 값을 가져온다는 것을 말해준다.

numberOfRooms에 대한 접근이가 잠제적으로 실패할 수 있기 때문에 선택 연쇄는 Int?이나 "선택적 Int"형 값을 반환하려고 한다. 위 예제처럼 residence가 nil인 경우는 numberOfRooms에 대한 접근이 불가능하다는 사실을 반영하기 위해서 이 선택적 Int 역시 nil이 될 것이다.
numberOfRooms가 비선택적 Int 임에도 불구하고 참인 것을 명심해라. 선택 연쇄를 통해 질의한다는 것은 numberOfRooms가 Int 대신 Int?를 항상 반환할 것이라는 것을 의미한다.
john.residence에 Residence 인스턴스를 할당할 수 있는데 그러면 더이상 nil 값은 존재하지 않게 된다.
>john.residence = Residence()

john.residence는 실체 Residence 인스턴스를 이제 가지게 되었다. 만약 예전과 동일한 선택 연쇄를 사용해 접근하려고 하면, 1이라는 numberOfRooms 기본값을 가지는 Int?가 반환될 것이다.

>if let roomCount = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}
// prints "John's residence has 1 room(s)."

선택 연쇄를 위한 모델(Model) 클래스(Class) 선언

프로퍼티, 메소드, 서브스크립트를 호출하는 것 같은 한단계 더 깊은 선택 연쇄을 사용할 수 있다. 이는 상호관계있는 타입간의 복잡한 모델에서 서브 프로퍼티(subproperty)를 파고 들 수 있게 해주고 그 서브 프로터티에 프로퍼티와 메소드, 서브스크립트에 접근할 수 있는지 아닌지를 확인할 수 있게 해준다.
다음 코드 조각은 다단계 선택 연쇄 예를 포함한 몇가지 순차적인 예제에서 사용될 4개의 모델 클래스를 정의한다. 이 클래스들은 위에 나온 Person과 Residence 모델에 Room과 Address 클래스를 추가하고 연관 프로퍼티와 메소드, 서브스크립트를 확장한다.
Person 클래스는 이전과 동일한 방법으로 정의한다.
>class Person {
var residence: Residence?
}

Residence 클래스는 이전보다 조금 복잡해졌다. 이번에는 Residence 클래스에 Room[] 타입의 빈 배열로 초기화된 rooms라는 변수 프로퍼티를 선언한다.
>‘class Residence {
var rooms = Room[]()
var numberOfRooms: Int {
return rooms.count
}
subscript(i: Int) -> Room {
return rooms[i]
}
func printNumberOfRooms() {
println("The number of rooms is \(numberOfRooms)")
}
var address: Address?
}’

이번 버전 Residence는 Room 인스턴스 배열을 저장하기 때문에, 그 numberOfRooms 프로퍼티는 저장된 프로퍼티가 아닌 계산된 프로퍼티로 구현했다. 계산된 numberOfRooms 프로퍼티는 단순히 rooms 배열에서 count 프로퍼티의 값을 반환한다.
그 rooms 배열에 접근하기 위한 바로가기로 이번 버전 Residence는 읽기만 가능한 서브 스크립트를 제공하는데 서브스크립트에게 전달받는 인덱스(index)가 적합할 것이라는 가정으로 시작해보겠다. 만약 인덱스가 적합하다면, 서브스크립트는 rooms 배열의 요청받은 인덱스의 방정보를 반환할 것이다.
또한 이번 버전 Residence는 printNumberOfRooms라는 이름의 메소드를 제공하는데 단순히 Residence에 방 갯수를 출력한다.
마지막으로 Residence에 Address?이란 타입으로 address라는 선택적 프로퍼티를 선언한다. 이를 위한 Address 클래스 타입은 밑에 정의하겠다.
rooms 배열에 사용하는 Room 클래스는 name이라는 프로퍼티 하나를 가지는 간단한 클래스인데 이는 적절한 방이름을 설정하기 위한 초기화 역할(initializer)을 한다.
>class Room {
let name: String
init(name: String) { self.name = name }
}

이 모델의 마지막 클래스는 Address이다. 이 클래스는 String? 타입의 선택적 프로퍼티를 3개 가지고 있다. 그 중 2개는 buildingName과 buildingNumber 인데 주소를 구성하는 특정 빌딩에 대한 구분을 짓기 위한 대체 수단이다. 3번째 프로퍼티인 street는 그 주소의 도로이름에 사용한다.
>class Address {
var buildingName: String?
var buildingNumber: String?
var street: String?
func buildingIdentifier() -> String? {
if buildingName {
return buildingName
} else if buildingNumber {
return buildingNumber
} else {
return nil
}
}
}

또한 Address 클래스는 String? 반환값을 가지는 buildingIdentifer 이란 이름의 메소드를 제공한다. 이 메소드는 buildingName과 buildingNumber 프로퍼티를 확인해서 만약 buildingName이 값을 가진다면 그 값을 혹은 buildingNumber이 값을 가진다면 그 값을, 둘다 값이 없다면 nil을 반환한다.

##선택 연쇄를 통한 프로퍼티 호출
강제 랩핑 해제(Forced Unwrapping) 대안으로써 선택 연쇄에서 봤던 것처럼 선택 연쇄를 선택적 값에 대한 프로퍼티 접근에 접근할 수 있는지 만약 프로퍼티 접근이 가능한지 확인하기 위해 사용할 수 있다. 그러나 선택 연쇄를 통해 프로퍼티의 값을 설정하는 것은 할 수 없다.
위에 정의한 새로운 Person 인스턴스를 사용해 클래스를 만들어 이전처럼 numberOfRooms 프로퍼티에 접근하기를 시도해본다.
>let john = Person()
if let roomCount = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}
// prints "Unable to retrieve the number of rooms."

john.residence가 nil이기 때문에 이 선택 연쇄를 예전과 동일한 방식으로 호출했지만 에러 없이 실패한다.

##선택연쇄를 통한 메소드 호출
선택 연쇄를 사용해서 선택적 값을 호출하고 메소드 호출이 성공했는지 여부를 확인해볼 수 있다. 설렁 메소드가 반환값을 정의하지 않더라고 할 수 있다.
Residence 클래스에 있는 printNumberOfRooms 메소드는 numberOfRooms의 현재 값을 출력한다. 그 메소드는 다음과 같을 것이다.
>func printNumberOfRooms() {
println("The number of rooms is \(numberOfRooms)")
}

이 메소드는 반환값을 명시하지 않았다. 그러나 반환형이 없는 함수와 메소드는 Functions Without Return Values에 나와 있는 것처럼 암시적으로 Void 타입을 반환하게 된다.
만약 선택 연쇄에 있는 선택지 값에 이 메소드를 호출한다면, 메소드 반환형은 Void가 아니라 Void?이 될 것이다. 선택 연쇄를 통해 호출될 때 선택적 타입은 항상 반환 값을 가지기 때문이다. 이는 메소드가 반환값이 정의되어 있지 않더라도 printNumberOfRooms 메소드를 호출이 가능한지를 if문을 써서 확인할 수 있게 한다. printNumberOfRooms에서 암시적 반환값은 만약 메소드가 선택 연쇄를 통해 성공적으로 호출되었다면 Void와 동일할 것이고 그렇지 않다면 nil과 동일할 것이다.
>if john.residence?.printNumberOfRooms() {
println("It was possible to print the number of rooms.")
} else {
println("It was not possible to print the number of rooms.")
}
// prints "It was not possible to print the number of rooms."

##선택 연쇄를 통한 서브스크립트 호출
선택적값에 대한 서브스크립트에서 값을 가져와서 서브스크립트 호출이 성공했는지 확인하기 위해 선택 연쇄를 사용할 수 있다. 그러나 선택 연쇄를 통해 서브스크립트로 값을 설정하는 것은 할 수 없다.

>노트
선택연쇄를 통해 선택적값에 대한 서브스크립트를 접근할 때 서브스크립트 괄호(brace) 앞에 물음표를 놓아야 한다. 뒤가 아니다. 선택연쇄 물음표는 항상 선택적인 표현식의 뒤에 바로 따라나와야 한다.

아래 예는 Residence 클래스에 정의되어 있는 서브스크립트를 사용하는 john.residence 프로퍼티의 rooms 배열에 있는 첫번째 방이름을 검색하려고 하는 것이다. john.residence가 현재 nil이기 때문에 서브스크립트는 실패한다.
>if let firstRoomName = john.residence?[0].name {
println("The first room name is \(firstRoomName).")
} else {
println("Unable to retrieve the first room name.")
}
// prints "Unable to retrieve the first room name."

선택연쇄 물음표
chapter4
# 04 기본 연산자 (Basic Operators)
> Translator : 해탈 (kimqqyun@gmail.com)

연산자는 값을 확인 변경 합치기 위해 사용하는 특수 기호나 문구입니다. 예를 들어 더하기 연산자(`+`)는 두 숫자를 더합니다. (`let i = 1 + 2` 과 같이)
더 복잡한 예는 논리 AND 연산자 (`&&`) 포함입니다. (`enteredDoorCode && passedRetinaScan`)그리고 증가 연산자인 `++i`는 `i`의 값 `1`을 증가시키는 축약 연산자입니다.

Swift 는 대부분의 표준 C 연산자를 지원하며 일반적인 코딩 오류를 제거하는 몇가지 기능을 항샹향상 시켰습니다. 할당연산자 (`=`)나 항등 연산자(`==`)를 사용할때 실수를 방지하기 위해 값을 반환하지 않습니다.
산술연산자(`+` ,` -` ,`*`,`/` ,`%` 등)가 오버플로우를 감지하고 그들을 저장하는 유형의 허용된 값의 범위보다 크거나 작아 숫자로 작업할때 예기치 않은 결과를 방지 할 수 있습니다.
당신은 오버 플로우 연산자에 설명된대로 Swift의 오버플로우 연산자를 사용하여 오버플로 값을 선택할수 있습니다. 이것은 Overflow Operaters 에 설명되어 있습니다. // 링크

C 와 달리, Swift는 부동 소수점 숫자에 나머지 (`%`) 계산을 수행 할 수 있습니다. Swift는 또한 2개의 범위 연산자를 제공합니다. (`A..B`) 그리고 (`A...B`) 이며 값의 범위를 표현하기 위한 연산자이고 이것은 C 에서 찾을 수 없습니다.

이 장에서는 Swift의 일반적인 연산자를 설명합니다. 고급 연산자는 고급 연산자(Advanced Operator) 장에 있습니다, 그리고 사용자 정의 연산자를 정의하고 사용자 정의 형식에 대한 표준 연산자를 구현하는 방법에 대해 설명합니다.

## 용어 (Teminology)
연산자는 단항, 이진, 그리고 삼항이 있습니다.

- 단항 연산자는 단일 대상에서 작동합니다. (예 `-a`) 단항 전위 연산자를 바로 앞에 나타내고, (예 `!b`) 단항 후위 연산자는 타겟이후에 즉시 나타납니다. (예 `i++`)
- 이항 연산자는 두개의 대상에 작동하며 그들의 두 대상 사이에 나타납니다. 왜냐하면 중위연산자입니다. (예 `2 + 3`)
- 삼항 연산자는 세 가지 대상에 작동합니다. C 처럼 , Swift는 하나의 삼항연산자, 삼항 조건 연산자가 (`a ? b : c`)

연산자에 영향을 주는 값은 피연산자 입니다. 식 `1 + 2` 는 이항 연산자와 두 피연산자의 값은 `1`과 `2`입니다.

## 할당 연산자
할당 연산자는 `(a = b)` 초기화 하거나 `b` 의 값을 `a` 에 할당하는것이다.
```
let b = 100
var a = 5
a = b
// a 는 이제 10 과 같다.
```

만약 오른쪽이 같은 여러 값을 가진 튜플의 경우, 그 요소는 한번에 여러개의 상수 또는 변수로 분해 될수 있다.
```
let (x, y) = (1, 2)
// x 는 1 과 같다 그리고 y 는 2 와 같다.
```

C 와 Objective-C의 대입 연산자와는 달리, Swift의 대입 연산자 자체가 값을 반환하지 않습니다. 다음 구문은 유효하지 않습니다.
```
if x = y {
// x = y가 값을 반환하지 않기 때문에 이것은 유효하지 않다,
}
```

이 기능은 실수로 (`==`) 연산자를 사용하여 막는것은 (`=`)를 대신 사용하는것을 방지하기 떄문입니다. `if x = y` 가 유효하지 않게 함으로써 Swift 코드에서 이러한 종류의 오류를 방지하는데 도움이 됩니다.

## 산술 연산자
Swift 는 4가지의 산술연산자가 모든 숫자 타입을 지원합니다.

- 덧셈 (`+`)
- 뺼셈 (`-`)
- 곱셈 (`*`)
- 나눗셈 (`/`)

```
1 + 2 // 3 과 같다
5 - 3 // 2 와 같다
2 * 3 // 6 과 같다
10.0 / 2.5 // 4.0 과 같다
```
C 및 Objective-C의 산술 연산자와는 달리 Swift 산술 연산자는 값이 기본적으로 오버플로우하는것을 허용하지 않는다. Swift 오버플로우 연산자를 사용하여 값 오버플로 동작을 선택할 수있습니다. Overflow Operators를 참조하십시오. // 링크

또한 덧셈 연산자는 String 문자열을 지원한다.
```
"hello, " + "world" // "hello, world" 와 같다
```

두 개의 `Character` 값이거나 하나는 `Character` 값 그리고 하나는 `String` 값일때 두 개를 함께 더해서 새로운 `String` 값을 만들 수 있습니다.

```
‘let dog: Character = "🐶🐶
let cow: Character = "🐮"
let dogCow = dog + cow
// dogCow is equal to "🐶🐮"
```
이것에 대해선 Strings and Characters 또한 참조 바란다. // 링크

## 나머지 연산자
나머지 연산자는 (`a % b`) `b` 의 많은 배수가 `a`에 맞게 곱해지며 그리고 남아 있는 값을 반환합니다. (이는 나머지 라고 불립니다.)

> NOTE

> 나머지 연산자는 (%) 또한 모듈로 연산으로 다른 언어에 알려져있다. 그러나 Swift에서의 동작은 음수를 의미한다. 엄격히 말하면, 모듈로 연산보다는 나머지 연산이다.

여기에 나머지 연산의 동작이 어떻게 되는지 있다. ` 9 % 4 ` 을 계산해보면, 당신은 첫번째로 `4`들을 `9`에 맞게 맞출것이다.
![remainderinteger_2x.png](images/remainderinteger_2x.png)


당신은 `4`들을 9에 맞추었고 그리고 나머지는 `1`이다. (오렌지 색깔을 보라)

Swift에서는 이렇게 쓰여진다

9 % 4 // 1과 같다

a % b 의 답을 측정해보면, % 계산 연산자는 나머지 출력과 = 연산자를 반한단다.

`a = (b x 배수) + 나머지`

`배수`가 `a` 내부의 맞는 가장 큰 수일 경우다.

9 와 4를 대입 할경우

` 9 = (4 × 2) + 1 `

a 의 값이 음수 일때도 같은 메소드가 지원되며 나머지 값이 음수가 나온다.

`-9 % 4 // -1과 같다`

-9 와 4 를 넣으면 다음 과 같은 식이 나온다.

`-9 = (4 × -2) + -1`

나머지 값이 `-1`이 주어진다.

`b`의 부호는 `b`의 음의 값이 무시됩니다. 이것은 `a % b` 와 `a % -b`는 항상 같은 대답을 주고 있다는 것을 의미한다.

## 부동 소수점 나머지 연산
C 와 Objective-C의 나머지 연산과는 달리, Swift의 나머지 연산은 부동 소수점 연산 또한 지원합니다.

`8 % 2.5 // 2.5와 같음`
예를 들어 8을 2.5로 나누었을때 3과 같다 나머지는 0.5와 같다. 그리고 나머지 연산이 반환하는 값은 Double 타입의 0.5이다.
![remainderfloat_2x.png](images/remainderfloat_2x.png)


## 증가연산자와 감소 연산자
C와 같이, Swift는 증가 연산자(`++`)와 감소 연산자(`--`)를 제공한다. 이것은 숫자 변수 `1`를 증가시키거나 감소시키는 축약형이다. 정수형과 부동소수점형을 연산자와 같이 사용 가능하다.
```
var i = 0
++i // i 는 이제 1과 같다
```

만약 `++i` 호출마다 `i`의 값은 `1` 씩 증가된다. 기본적으로 `++i` 는 `i = i + 1` 의 약어이다. 마찬가지로 `--i`를 `i = i - 1` 의 약어로 사용할 수 있습니다.

`++` 와 `--` 기호는 전위연산자 또는 후위연산자로 사용이 가능합니다. `++i` 와 `++i`는 둘다` i`의 값을` 1` 증가시키는 방법입니다. 비슷하게, `--i` 와 `i--`는 `i`의 값을 `1` 감소시키는 방법입니다.

이러한 수정연산자는 i 와 그리고 반환값 까지 변화시킵니다. 만약 i 에 저장된 값을 증가 또는 감소 할 경우, 반환값을 무시 할 수있습니다. 그러나 반환된 값을 사용할 경우, 당신은 다음과 같은 규칙에 따라 접두사 또는 연산자의 후위버전을 사용하는지 여부에 따라 달라집니다.

- 만약 변수 앞에 쓰여질 경우, 값이 증가한 후에 반환된다.
- 반약 변수 뒤에 쓰여질 경우, 값이 반환된 뒤에 증가된다.

예제 코드 (For example:)
```
var a = 0
let b = ++a
// a 그리고 b는 지금 a 둘다 1과 같다.
let c = a++
// a 는 지금 2, 그러나 c는 이전의 값인 1이 이미 설정되어있다.
```

위의 예제코드에서 `let b = ++a` 는 `a`를 반환하기 전에 `a`를 증가시킨다. 이 방법은 a 와 b 하나의 새로운 값이 동등한 이유이다.

그러나, `let c = a++` 는 `a`를 반환한 후에 `a`를 증가시킨다. 이 뜻은 `c`가 없은 값은 예전의 값인 `1`이며 `a`에게는 업데이트 된 `2`와 같다.

당신은 i++의 특정동작을 필요로 하지 않는한, 이것은 당신이 ++i 나 --i를 사용하는것이 좋습니다. 왜냐하면 그것은 모든 경우에 `i`를 수정하고 결과를 반환하는 예상된 동작을 가지기 때문입니다.

##단항 마이너스 연산자
숫자 값의 부호는 접두어 -를 사용하여 전환할수 있다. 이것은 단항 마이너스 연산자로 알려진것이다.

```
let three = 3
let minusThree = -three // minusThree equal -3
let plusThree = -minusThree // plus equal 3, or "minus minus three"
```
단항 마이너스 연산자는 공백없이 작동하는 값 바로 앞에 추가 됩니다.

##단항 플러스 연산자
단항 플러스 연산자(+)는 간단하게 변경하지 않고, 값을 반환합니다.

```
let minusSix = -6
let alsoMinusSix = +minusSix // alsoMinusSix equals -6
```

플러스 연산자가 있음에도 불구하고 실제로 아무것도 하지 않지만, 당신은 또한 단항 마이너스 연산자를 사용하는 경우 양수에 대한 코드대칭에 사용할 수 있습니다.

## 복합 할당 연산자
C와 같이 Swift는 다른 작업에 할당(=)을 결합하는 복합 할당 연산자를 제공합니다. 한 예를 들어 덧셈 할당 연산자입니다 (+=):
```
var a = 1
a += 2
// a 는 3과 같다
```

표현식 `a += 2` 는 `a = a + 2` 의 축약형이다. 효과적으로 한 연산자가 가산 및 할당이 동시에 작업과 결합이 된다.

>NOTE
>
> 복합 할당 연산자는 값을 반환하지 않는다. 당신은 `let b = a += 2` 이러한 코드를 작성할수 없다. 예를 들어 이러한 코드는 위의 증가 및 감소 연산자와는 다릅니다.

복합 할당 연산자의 전체 목록은 Expressions 에서 찾을 수 있습니다. // 링크

## 비교 연산자
Swift는 C의 정식 비교연산자를 지원합니다.

- 같음 연산자 (`a == b`)
- 같지 않음 연산자 (`a != b`)
- 보다 큰 (`a > b`)
- 보다 작은(`a < b`)
- 보다 크거나 같은 (`a >= b`)
- 보다 작거나 같은 (`a <= b`)

>NOTE
>
>Swift는 또한 두 개체 참조가 동일한 인스턴스 객체를 참조하고 있는지 여부를 테스트 하는 연산자를 지원합니다. (`===` 와 `!==`) 자세한 내용은 Classes and Structures를 참조하십시오 // 링크

비교 연산자의 각 문장이 참인지 여부를 나타내는 `Bool` 값을 반환합니다 :

```
1 == 1 // 참
2 != 1 // 참
2 > 1 // 참
1 < 2 // 참
1 >= 1 // 참
2 <= 1 // 거짓

```

비교 연산자는 종종 if문 같은 조건문에 사용된다 :

```
let name == "world"
if name == "world" {
println("hello, world")
} else {
println("I'm sorry \(name), but I don't recognize you")
}
```
`if`에 대한 더 많은 정보는 Control Flow를 참조하기 바란다. // 링크

## 삼항 조건 연산자
삼항 조건 연산자는 특별한 연산자와 세개의 파트로 이루어져있습니다.
양식은 이러합니다. (`question ? answer1 : answer2`)
이 `question`이 참인지 거짓인지에 따라 두 식중 하나를 평가하기 위한 축약어입니다. 만약 `question` 이 참이면 `answer1`을 계산하고 값을 반환합니다; 그렇지 않으면 `answer2`를 계산하고 값을 반환합니다.

삼항 조건 연산자는 아래의 코드에 대한 속기입니다.

```
if question {
answer1
} else {
answer2
}
```
이것은 테이블 행의 픽셀 높이를 계산하는 예제입니다. 행의 헤더가 있다면 컨텐츠의 높이가 50 픽셀이상이고 행의 헤더가 없다면 20픽셀 보다 큰것입니다.:

```
let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
// rowHeight 는 90과 같다
```

위의 예제코드는 아래 코드의 속기입니다.
```
let contentHeight = 40
let hasHeader = true
var rowHeight = contentHeight
if hasHeader {
rowHeight = rowHeight + 50
} else {
rowHeight = rowHeight + 20
}

```

첫번째 예제의 삼항 조건 연산자의 사용은 `rowheight`에 단 한줄의 코드에 올바른 값으로 설정될 수 있음을 의미합니다. 이것은 두 번째 예제코드보다 간결하고 그 값이 `if` 문 내에서 수정될 필요가 없기 떄문에 이것은 `rowheight`가 변수가 될 필요성이 없어집니다.

삼항 조건 연산자는 두 식의 어떤 결정을 고려하는것을 위해 효율적인 속기를 제공합니다. 그러나 삼항 조건 연산자는 주의해서 다뤄야 합니다. 남용하면 그 간결함은 읽기 어려운 코드로 이어질 수 있습니다. 하나의 복합 문에 삼항 조건 연산자와 다중 인스턴스를 결합하는것을 피하세요.

## 범위 연산자
Swift는 두 개의 범위연산자를 지원하며 이 축약어는 값의 범위를 표현합니다.

### 폐쇄 범위 연산자
폐쇄 범위 연산자(`a...b`)는 `a`에서 `b` 까지의 범위를 정의합니다. 그리고 `a`와 `b`의 값을 포함합니다.

폐쇄 범위 연산자는 `for-in` 루프와 같이 사용하고자 하는 값 범위에서 반복할때 폐쇄 범위 연산자는 유용합니다.

```
for index in 1...5 {
println("\(index) time 5 is \(index * 5)")
}
// 1번쨰 반복 5 is 5
// 2번쨰 반복 5 is 10
// 3번쨰 반복 5 is 15
// 4번쨰 반복 5 is 20
// 5번쨰 반복 5 is 25
```
`for-in` 루프에 대해서는 Control Flow 항목을 참조하시오 // 링크

### 반 폐쇄 범위 연산자
반 폐쇄 범위 연산자 (`a..b`)는 a 에서 b 로 실행되는 범위를 정의하지만 b가 포함되어 있지 않습니다. 그것은 최종값이 아니며 처음 값을 포함하고 있기 때문에 반폐쇄라고 합니다.

반 폐쇄 범위는 특히 0을 기반으로한 목록 또는 배열로 작업할때 유용합니다. 그것은 리스트의 길이(포함안되는)까지 계산하는데 유용합니다.
```
let names = ["Anna", "Alex", "Brian", "Jack"]
let count = name.count
for i in 0.count {
println("Person \(i + 1) is called \(names[i]")
}
// Person 1 is called Anna
// Person 2 is called Alex
// Person 3 is called Brian
// Person 4 is called Jack
```
배열에는 4개의 항목이 포함되어있습니다. 하지만 반 폐쇄 범위기 때문에 `0..count` 는 단지 3까지만 카운트 합니다. (배열의 마지막 항목의 인덱스)
arrays에 대해 더 참조하고 싶다면 Arrays 항목 를 참조하시오 // 링크

## 논리 연산자
논리 연산자는 `true`와 `false` 불리언 논리 값을 수정하거나 결합합니다. Swift는 C 기반 언어의 세 가지 표준 논리 연산자를 지원합니다.

- NOT (!a)
- AND (a && b)
- OR (a || b)

##논리 NOT 연산자
논리 NOT 연산자(`!a`)는 불리언 값인 `true` 값을 반전시키고 `false` 값은 `true` 가 된다.

논리 NOT 연산자는 전위 연산자입니다. 값 앞에 연산을 공백없이 즉시 표현 할 수 있습니다. 이것은 "`not` a"로 바로 읽을 수 있으며 다음의 예제에서 볼 수 있습니다.

```
let allowedEntry = false
if !allowedEnrty {
println("ACCESS DENIED")
}
// prints "ACCESS DENIED"
```
`if !allowedEntry` 는 "if not allowed entry" 로 읽을 수 있습니다.
즉 `allowedEntry`이 false인 경우 라인 이후의 `not allowed entry` 가 `true`인 경우에 해당할 경우로 실행됩니다.
이 예제에서와 같이 불리언 상수와 변수 이름의 주의 깊은 선택은 이중 부정 또는 혼란한 논리구문을 피하면서 읽기 쉽고 간결한 코드를 유지하는데 도움이 될 수 있습니다.

## 논리 AND 연산자

논리 AND 연산자(`a && b`)의 overall expression은 두 값이 모두 `true`이어야 `true`가 됩니다.

반대로 두 값이 `false` 이면 overall expression 또한 `false` 입니다. 사실 첫번째 값이 `false` 인 경우 두번째 값이 evaluated 되지 않습니다. 그것을 가능할수 없기 떄문에 overall expression이 `true`와 같게 됩니다. 이는 short-circuit evaluation 로 불린다.

이 예제에서는 두 개의 `Bool`값을 고려하여 만약 두 값이 `true` 에만 액세스 할 수 있습니다.

```
let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
println("Welcome!")
} else {
println("ACCEss DENIED")
}
// prints "ACCESS DENIED"
```
## 논리 OR 연산자
논리 OR 연산자(`a || b`)는 인접한 파이프 문자로 만든 중위연산자 입니다. overall expression 이 `true`가 될 때 까지 두 개의 값 중 하나만이 참이어야 하는 논리식을 만드는데 사용합니다.

위의 논리 AND 연산자처럼 논리 OR 연산자는 식을 고려할떄 short-circuit evaluation을 사용합니다. 논리 OR식의 좌측에 `true`가 해당하는 경우는 overall expression 식의 결과를 변경 할수 있기 때문에 우측은 계산되지 않는다.

아래의 예제에서 첫 번째 `Bool` 값(`hasDoorKey`)은 `false`이지만 두 번째 값(`knowsOverridePassword`)는 `true`이다. 하나의 값 이`true`이기 떄문에 overall expression은 `true`로 평가하고 액세스가 허용됩니다.

```
let hasDoorKey = false
let knowOverridePassword = true
if hasDoorKey || knowOverridePassword {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "Welcome!"
```
## 복합 논리 연산자

당신은 여러 논리 연산자를 결합하여 복합 논리 연산자를 만들 수 있습니다.
```
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowOverridePassword {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "Welcome!"
```
이 예제는 && 및 || 연산자를 여러개 사용하려 긴 복합 표현식을 만들었습니다. 그러나 && 와 || 연산자는 여전히 두 개의 값에 대해 작동하므로 이는 실제로 서로 세개가 연결된 작은 표현입니다.
이것은 이렇게 읽을 수 있습니다:

만약 우리가 문의 코드를 입력하고 망막 검사를 통과한경우; 우리가 유효한 도어 키가 있는 경우이거나 긴급 재정의 암호를 알고있는 경우 다음 액세스 할 수 있습니다.

`enteredDoorCode` 와 `passedRetinaScan` 그리고 `hasDoorKey` 의 값에 기초하여 처음 작은 표현식은 `false`이다. 그러나 긴급 재정의 암호가 `true`로 알려져있다 ,그래서 전체 복합 표현식은 여전히 `true`로 평가됩니다.

## 괄호 명시
괄호가 엄격히 필요하지 않은경우, 읽기 복잡한 표현의 의도록 쉽게 만들수 있는 경우에 괄호가 포함되는것이 유용한 경우가 종종 있다.

위의 door access 예제 코드에서 그것의 의도를 명시적으로 확인하기 위해 복합 표현식의 첫번째 부분을 괄호를 추가하는데에 유용합니다.

```
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowOverridePassword {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "Welcome!"
```
괄호는 처음 두 값을 전체 논리에서 별도의 가능한 상태의 일부로 분명히 간주되게 만듭니다. 복합식의 출력이 변하지는 않지만 전체적인 목적이 독자에게 명확해집니다. 가독성은 항상 간결함을 선호합니다; 괄호의 사용은 당신의 의도를 확실히 파악하는데 도움이 됩니다.

images/chapter10-fig1
images/chapter10-fig2