├── CONTRIBUTING.md ├── LICENSE ├── README.md └── README_KR.md /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | If you want to suggest a change or addition that will help accomplish 2 | [the goals](README.md) of this style guide, please open a pull request that: 3 | 4 | 1. Explains the guideline 5 | 1. Demonstrates the guideline with more-or-less valid example code 6 | 1. Justifies the guideline by explaining the rationale behind it 7 | 8 | Just note that all suggestions are open to discussion and debate! :smile: 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A guide to our Swift style and conventions. 2 | 3 | This is an attempt to encourage patterns that accomplish the following goals (in 4 | rough priority order): 5 | 6 | 1. Increased rigor, and decreased likelihood of programmer error 7 | 1. Increased clarity of intent 8 | 1. Reduced verbosity 9 | 1. Fewer debates about aesthetics 10 | 11 | If you have suggestions, please see our [contribution guidelines](CONTRIBUTING.md), 12 | then open a pull request. :zap: 13 | 14 | ---- 15 | 16 | #### Whitespace 17 | 18 | * Tabs, not spaces. 19 | * End files with a newline. 20 | * Make liberal use of vertical whitespace to divide code into logical chunks. 21 | * Don’t leave trailing whitespace. 22 | * Not even leading indentation on blank lines. 23 | 24 | 25 | #### Prefer `let`-bindings over `var`-bindings wherever possible 26 | 27 | Use `let foo = …` over `var foo = …` wherever possible (and when in doubt). Only use `var` if you absolutely have to (i.e. you *know* that the value might change, e.g. when using the `weak` storage modifier). 28 | 29 | _Rationale:_ The intent and meaning of both keywords is clear, but *let-by-default* results in safer and clearer code. 30 | 31 | A `let`-binding guarantees and *clearly signals to the programmer* that its value is supposed to and will never change. Subsequent code can thus make stronger assumptions about its usage. 32 | 33 | It becomes easier to reason about code. Had you used `var` while still making the assumption that the value never changed, you would have to manually check that. 34 | 35 | Accordingly, whenever you see a `var` identifier being used, assume that it will change and ask yourself why. 36 | 37 | #### Avoid Using Force-Unwrapping of Optionals 38 | 39 | If you have an identifier `foo` of type `FooType?` or `FooType!`, don't force-unwrap it to get to the underlying value (`foo!`) if possible. 40 | 41 | Instead, prefer this: 42 | 43 | ```swift 44 | if let foo = foo { 45 | // Use unwrapped `foo` value in here 46 | } else { 47 | // If appropriate, handle the case where the optional is nil 48 | } 49 | ``` 50 | 51 | Alternatively, you might want to use Swift's Optional Chaining in some of these cases, such as: 52 | 53 | ```swift 54 | // Call the function if `foo` is not nil. If `foo` is nil, ignore we ever tried to make the call 55 | foo?.callSomethingIfFooIsNotNil() 56 | ``` 57 | 58 | _Rationale:_ Explicit `if let`-binding of optionals results in safer code. Force unwrapping is more prone to lead to runtime crashes. 59 | 60 | #### Avoid Using Implicitly Unwrapped Optionals 61 | 62 | Where possible, use `let foo: FooType?` instead of `let foo: FooType!` if `foo` may be nil (Note that in general, `?` can be used instead of `!`). 63 | 64 | _Rationale:_ Explicit optionals result in safer code. Implicitly unwrapped optionals have the potential of crashing at runtime. 65 | 66 | #### Prefer implicit getters on read-only properties and subscripts 67 | 68 | When possible, omit the `get` keyword on read-only computed properties and 69 | read-only subscripts. 70 | 71 | So, write these: 72 | 73 | ```swift 74 | var myGreatProperty: Int { 75 | return 4 76 | } 77 | 78 | subscript(index: Int) -> T { 79 | return objects[index] 80 | } 81 | ``` 82 | 83 | … not these: 84 | 85 | ```swift 86 | var myGreatProperty: Int { 87 | get { 88 | return 4 89 | } 90 | } 91 | 92 | subscript(index: Int) -> T { 93 | get { 94 | return objects[index] 95 | } 96 | } 97 | ``` 98 | 99 | _Rationale:_ The intent and meaning of the first version is clear, and results in less code. 100 | 101 | #### Always specify access control explicitly for top-level definitions 102 | 103 | Top-level functions, types, and variables should always have explicit access control specifiers: 104 | 105 | ```swift 106 | public var whoopsGlobalState: Int 107 | internal struct TheFez {} 108 | private func doTheThings(things: [Thing]) {} 109 | ``` 110 | 111 | However, definitions within those can leave access control implicit, where appropriate: 112 | 113 | ```swift 114 | internal struct TheFez { 115 | var owner: Person = Joshaber() 116 | } 117 | ``` 118 | 119 | _Rationale:_ It's rarely appropriate for top-level definitions to be specifically `internal`, and being explicit ensures that careful thought goes into that decision. Within a definition, reusing the same access control specifier is just duplicative, and the default is usually reasonable. 120 | 121 | #### When specifying a type, always associate the colon with the identifier 122 | 123 | When specifying the type of an identifier, always put the colon immediately 124 | after the identifier, followed by a space and then the type name. 125 | 126 | ```swift 127 | class SmallBatchSustainableFairtrade: Coffee { ... } 128 | 129 | let timeToCoffee: NSTimeInterval = 2 130 | 131 | func makeCoffee(type: CoffeeType) -> Coffee { ... } 132 | ``` 133 | 134 | _Rationale:_ The type specifier is saying something about the _identifier_ so 135 | it should be positioned with it. 136 | 137 | Also, when specifying the type of a dictionary, always put the colon immediately 138 | after the key type, followed by a space and then the value type. 139 | 140 | ```swift 141 | let capitals: [Country: City] = [ Sweden: Stockholm ] 142 | ``` 143 | 144 | #### Only explicitly refer to `self` when required 145 | 146 | When accessing properties or methods on `self`, leave the reference to `self` implicit by default: 147 | 148 | ```swift 149 | private class History { 150 | var events: [Event] 151 | 152 | func rewrite() { 153 | events = [] 154 | } 155 | } 156 | ``` 157 | 158 | Only include the explicit keyword when required by the language—for example, in a closure, or when parameter names conflict: 159 | 160 | ```swift 161 | extension History { 162 | init(events: [Event]) { 163 | self.events = events 164 | } 165 | 166 | var whenVictorious: () -> () { 167 | return { 168 | self.rewrite() 169 | } 170 | } 171 | } 172 | ``` 173 | 174 | _Rationale:_ This makes the capturing semantics of `self` stand out more in closures, and avoids verbosity elsewhere. 175 | 176 | #### Prefer structs over classes 177 | 178 | Unless you require functionality that can only be provided by a class (like identity or deinitializers), implement a struct instead. 179 | 180 | Note that inheritance is (by itself) usually _not_ a good reason to use classes, because polymorphism can be provided by protocols, and implementation reuse can be provided through composition. 181 | 182 | For example, this class hierarchy: 183 | 184 | ```swift 185 | class Vehicle { 186 | let numberOfWheels: Int 187 | 188 | init(numberOfWheels: Int) { 189 | self.numberOfWheels = numberOfWheels 190 | } 191 | 192 | func maximumTotalTirePressure(pressurePerWheel: Float) -> Float { 193 | return pressurePerWheel * numberOfWheels 194 | } 195 | } 196 | 197 | class Bicycle: Vehicle { 198 | init() { 199 | super.init(numberOfWheels: 2) 200 | } 201 | } 202 | 203 | class Car: Vehicle { 204 | init() { 205 | super.init(numberOfWheels: 4) 206 | } 207 | } 208 | ``` 209 | 210 | could be refactored into these definitions: 211 | 212 | ```swift 213 | protocol Vehicle { 214 | var numberOfWheels: Int { get } 215 | } 216 | 217 | func maximumTotalTirePressure(vehicle: Vehicle, pressurePerWheel: Float) -> Float { 218 | return pressurePerWheel * vehicle.numberOfWheels 219 | } 220 | 221 | struct Bicycle: Vehicle { 222 | let numberOfWheels = 2 223 | } 224 | 225 | struct Car: Vehicle { 226 | let numberOfWheels = 4 227 | } 228 | ``` 229 | 230 | _Rationale:_ Value types are simpler, easier to reason about, and behave as expected with the `let` keyword. 231 | 232 | #### Make classes `final` by default 233 | 234 | Classes should start as `final`, and only be changed to allow subclassing if a valid need for inheritance has been identified. Even in that case, as many definitions as possible _within_ the class should be `final` as well, following the same rules. 235 | 236 | _Rationale:_ Composition is usually preferable to inheritance, and opting _in_ to inheritance hopefully means that more thought will be put into the decision. 237 | 238 | 239 | #### Omit type parameters where possible 240 | 241 | Methods of parameterized types can omit type parameters on the receiving type when they’re identical to the receiver’s. For example: 242 | 243 | ```swift 244 | struct Composite { 245 | … 246 | func compose(other: Composite) -> Composite { 247 | return Composite(self, other) 248 | } 249 | } 250 | ``` 251 | 252 | could be rendered as: 253 | 254 | ```swift 255 | struct Composite { 256 | … 257 | func compose(other: Composite) -> Composite { 258 | return Composite(self, other) 259 | } 260 | } 261 | ``` 262 | 263 | _Rationale:_ Omitting redundant type parameters clarifies the intent, and makes it obvious by contrast when the returned type takes different type parameters. 264 | 265 | #### Use whitespace around operator definitions 266 | 267 | Use whitespace around operators when defining them. Instead of: 268 | 269 | ```swift 270 | func <|(lhs: Int, rhs: Int) -> Int 271 | func <|<(lhs: A, rhs: A) -> A 272 | ``` 273 | 274 | write: 275 | 276 | ```swift 277 | func <| (lhs: Int, rhs: Int) -> Int 278 | func <|< (lhs: A, rhs: A) -> A 279 | ``` 280 | 281 | _Rationale:_ Operators consist of punctuation characters, which can make them difficult to read when immediately followed by the punctuation for a type or value parameter list. Adding whitespace separates the two more clearly. 282 | 283 | #### Translations 284 | 285 | * [中文版](https://github.com/Artwalk/swift-style-guide/blob/master/README_CN.md) 286 | * [日本語版](https://github.com/jarinosuke/swift-style-guide/blob/master/README_JP.md) 287 | * [한국어판](https://github.com/minsOne/swift-style-guide/blob/master/README_KR.md) -------------------------------------------------------------------------------- /README_KR.md: -------------------------------------------------------------------------------- 1 | Swift 스타일과 규칙 안내입니다. 2 | 3 | 다음 목표(대략적인 우선순위)를 이루는 패턴을 장려하려고 합니다: 4 | 5 | 1. 엄격성 증가, 프로그래머 에러의 가능성 감소 6 | 1. 목적의 명확성 증가 7 | 1. 중복 감소 8 | 1. 미학에 대한 논쟁을 줄임 9 | 10 | 만약 제안이 있으면, 우리의 [공헌 정책](CONTRIBUTING.md)를 보고 pull request를 보내주시기 바랍니다. :zap: 11 | 12 | ---- 13 | 14 | #### 공백 [원문](https://github.com/github/swift-style-guide#whitespace) 15 | 16 | * 공백이 아닌 탭 사용. 17 | * 파일 끝에 줄 바꿈. 18 | * 코드를 논리 단위로 나누도록 빈 줄을 아낌없이 사용. 19 | * 줄 끝에 공백을 남기지 않기. 20 | * 빈 줄에서 들여쓰기조차 안됨. 21 | 22 | 23 | #### `var` 바인딩보다 `let` 바인딩을 선호 [원문](https://github.com/github/swift-style-guide#prefer-let-bindings-over-var-bindings-wherever-possible) 24 | 25 | 가능하면(그리고 의심스럽더라도) `var foo = …` 보다 `let foo = …`을 사용합니다. 만약에 정말로 사용해야 할때만 `var`을 사용합니다. (즉, 값이 변할 것을 알고 있고, 예를 들면 `weak` 저장 수식어를 사용할 때입니다.) 26 | 27 | _이유:_ 두 키워드의 목적과 의미는 명확하지만, *기본적으로 let*이 더 안전하고 명확한 코드입니다. 28 | 29 | 프로그래머에게 `let`-바인딩은 값이 예상되고, 바뀌지 않을 것임을 보장하고 명확하게 전달합니다. 후속 코드는 변수의 용도를 더 쉽게 추측할 수 있습니다. 30 | 31 | 코드를 더 쉽게 이해하게 됩니다. `var`를 사용하는 동안 값이 변하지 않았음을 가정해가면서, 직접 확인해야 합니다. 32 | 33 | 따라서 `var` 식별자가 사용된 것을 볼 때마다, 값이 변할 것을 가정하고 스스로 왜 그런지 물어볼 것입니다. 34 | 35 | #### 옵셔널의 강제 언래핑 사용 피하기 [원문](https://github.com/github/swift-style-guide#avoid-using-force-unwrapping-of-optionals) 36 | 37 | 타입 `FooType?` 또는 `FooType!`의 `foo` 식별자가 있다면, 강제 언래핑으로 값(`foo!`)를 얻으려고 하지 마세요. 가능하면 말이죠. 38 | 39 | 대신에, 이 방식으로 하세요: 40 | 41 | ```swift 42 | if let foo = foo { 43 | // 여기에서 언래핑된 `foo` 값 사용 44 | } else { 45 | // 여기에 해당하는 경우, 옵셔널이 nil인 경우를 다루세요. 46 | } 47 | ``` 48 | 49 | 아니면 예를 들면 일부의 경우에서 Swift의 옵셔널 채이닝을 사용할 수 있습니다: 50 | 51 | ```swift 52 | // `foo`가 nil이 아니라면 함수가 호출됩니다. 만약 `foo`가 nil이라면 함수 호출을 무시합니다. 53 | foo?.callSomethingIfFooIsNotNil() 54 | ``` 55 | 56 | _이유:_ 명시적 옵셔널의 `if let`-바인딩 결과로 더 안전한 코드가 됩니다. 강제 언래핑은 런타임 크래시가 발생할 가능성이 많습니다. 57 | 58 | #### 암시적으로 언래핑된 옵셔널 피하기 [원문](https://github.com/github/swift-style-guide#avoid-using-implicitly-unwrapped-optionals) 59 | 60 | 만약에 `foo`가 nil이라면 `let foo: FooType!` 대신 `let foo: FooType?`를 가능하면 사용하세요.(주의, `!` 대신 `?` 사용할 수 있습니다.) 61 | 62 | _이유:_ 명시적 옵셔널이 더 안전한 코드입니다. 암시적으로 언래핑된 옵셔널은 런타임시 크래시의 원인이 될 수 있습니다. 63 | 64 | #### 읽기전용 속성과 서브스크립트에서 암시적 getter 선호 [원문](https://github.com/github/swift-style-guide#prefer-implicit-getters-on-read-only-properties-and-subscripts) 65 | 66 | 가능하면 읽기 전용 계산된 속성과 읽기 전용 서브스크립트에서 `get` 키워드는 생략합니다. 67 | 68 | 그래서 다음과 같이 작성합니다: 69 | 70 | ```swift 71 | var myGreatProperty: Int { 72 | return 4 73 | } 74 | 75 | subscript(index: Int) -> T { 76 | return objects[index] 77 | } 78 | ``` 79 | 80 | … 다음과 같이 작성하지 않습니다. 81 | 82 | ```swift 83 | var myGreatProperty: Int { 84 | get { 85 | return 4 86 | } 87 | } 88 | 89 | subscript(index: Int) -> T { 90 | get { 91 | return objects[index] 92 | } 93 | } 94 | ``` 95 | 96 | _이유:_ 첫 번째 버전의 목적과 의미가 명확하여 더 적은 코드가 됩니다. 97 | 98 | #### 항상 최상위 수준 정의를 명시적으로 접근 제어 지정 [원문](https://github.com/github/swift-style-guide#always-specify-access-control-explicitly-for-top-level-definitions) 99 | 100 | 최상위 수준 함수, 타입 그리고 변수는 항상 명시적 접근 제어 지정자가 있어야 합니다: 101 | 102 | ```swift 103 | public var whoopsGlobalState: Int 104 | internal struct TheFez {} 105 | private func doTheThings(things: [Thing]) {} 106 | ``` 107 | 108 | 그러나 이들 내 정의는 적절한 곳에 암묵적으로 접근 제어를 남길 수 있습니다: 109 | 110 | ```swift 111 | internal struct TheFez { 112 | var owner: Person = Joshaber() 113 | } 114 | ``` 115 | 116 | _이유:_ 최상위 수준 정의에서 더욱 명확하게 `internal`이 되는 것과 명시적으로 신중하게 생각하여 결정을 보장하기가 극히 드뭅니다. 정의 내에서 같은 접근 제어 지정자 재사용은 단지 중복되며, 일반적으로 기본값이 합당합니다. 117 | 118 | #### 타입을 지정할 때, 항상 식별자 뒤에 콜론을 연결 [원문](https://github.com/github/swift-style-guide#when-specifying-a-type-always-associate-the-colon-with-the-identifier) 119 | 120 | 식별자의 타입을 지정할 때, 항상 식발자 뒤에 콜론을 바로 붙이고, 공백 다음에 타입 이름이 붙습니다. 121 | 122 | ```swift 123 | class SmallBatchSustainableFairtrade: Coffee { ... } 124 | 125 | let timeToCoffee: NSTimeInterval = 2 126 | 127 | func makeCoffee(type: CoffeeType) -> Coffee { ... } 128 | ``` 129 | 130 | _이유:_ 타입 지정자는 _식별자_에 대해서 무언가를 이야기합니다. 그래서 타입 지정자는 식별자와 위치해야 합니다. 131 | 132 | 또한, 딕셔너리의 타입을 지정할 때, 항상 콜론은 키 타입 뒤에 위치해야 하며 공백 다음에 값 타입이 뒤따릅니다. 133 | 134 | ```swift 135 | let capitals: [Country: City] = [ Sweden: Stockholm ] 136 | ``` 137 | 138 | #### 필요할 때만 명시적으로 `self` 참조 [원문](https://github.com/github/swift-style-guide#only-explicitly-refer-to-self-when-required) 139 | 140 | self의 속성과 메소드에 접근할 때, `self`를 따로 적지 않습니다.(기본적으로 `self`는 암묵적 참조입니다.): 141 | 142 | ```swift 143 | private class History { 144 | var events: [Event] 145 | 146 | func rewrite() { 147 | events = [] 148 | } 149 | } 150 | ``` 151 | 152 | 클로저처럼 파라미터명이 충돌일 경우에만 명시적으로 `self` 키워드를 사용합니다.: 153 | 154 | ```swift 155 | extension History { 156 | init(events: [Event]) { 157 | self.events = events 158 | } 159 | 160 | var whenVictorious: () -> () { 161 | return { 162 | self.rewrite() 163 | } 164 | } 165 | } 166 | ``` 167 | 168 | _이유:_ 클로저 내에서 `self`의 캡처링 의미를 더 돋보이게 만들고, 다른 곳에서 장황하게 사용하는 것을 피할 수 있게 합니다. 169 | 170 | #### 클래스 보다 구조체를 선호 [원문](https://github.com/github/swift-style-guide#prefer-structs-over-classes) 171 | 172 | 클래스에서만 사용가능한 것들(identity, deinitializer 등)이 필요한 경우가 아니라면, 구조체로 구현하세요. 173 | 174 | 보통은 클래스를 사용하는 이유가, 상속이 (유일한) 이유는 아닙니다. 왜냐하면 다형성은 프로토콜이 제공할 수 있고, 구현의 재사용은 조립(Composition)을 통해서 가능합니다. 175 | 176 | 다음은 클래스 계층 구조 입니다: 177 | 178 | ```swift 179 | class Vehicle { 180 | let numberOfWheels: Int 181 | 182 | init(numberOfWheels: Int) { 183 | self.numberOfWheels = numberOfWheels 184 | } 185 | 186 | func maximumTotalTirePressure(pressurePerWheel: Float) -> Float { 187 | return pressurePerWheel * numberOfWheels 188 | } 189 | } 190 | 191 | class Bicycle: Vehicle { 192 | init() { 193 | super.init(numberOfWheels: 2) 194 | } 195 | } 196 | 197 | class Car: Vehicle { 198 | init() { 199 | super.init(numberOfWheels: 4) 200 | } 201 | } 202 | 203 | ``` 204 | 205 | 다음과 같이 프로토콜로 리팩토링되었습니다: 206 | 207 | ```swift 208 | protocol Vehicle { 209 | var numberOfWheels: Int { get } 210 | } 211 | 212 | func maximumTotalTirePressure(vehicle: Vehicle, pressurePerWheel: Float) -> Float { 213 | return pressurePerWheel * vehicle.numberOfWheels 214 | } 215 | 216 | struct Bicycle: Vehicle { 217 | let numberOfWheels = 2 218 | } 219 | 220 | struct Car: Vehicle { 221 | let numberOfWheels = 4 222 | } 223 | ``` 224 | 225 | _이유:_ 값 타입은 더 간단하고, `let` 키워드와 함께 예상대로 동작하여 쉽게 이해합니다. 226 | 227 | #### 기본적으로 클래스는 `final`로 작성 [원문](https://github.com/github/swift-style-guide#make-classes-final-by-default) 228 | 229 | 클래스는 `final`로 시작해야 합니다. 상속이 필요하다면 클래스는 서브클래스를 만들도록 할 수 있게 변경합니다. 심지어, 클래스 내 가능한 많은 정의는 `final`이 되어야 하고, 같은 규칙을 따릅니다. 230 | 231 | _이유:_ 일반적으로 구성은 상속을 선호하고, 아마도 상속을 선택하면 결정하는데 좀 더 많은 생각을 해야 합니다.(역자 주 - 상속 구조를 결정하기 위해 고민을 더 해야 한다고 생각됩니다.) 232 | 233 | #### 가능하면 타입 인자 생략하기 [원문](https://github.com/github/swift-style-guide#omit-type-parameters-where-possible) 234 | 235 | 매개 변수가 된 타입의 메소드는 수신자가 같을 때 받는 타입에 타입 매개 변수를 생략할 수 있습니다. 예를 들어: 236 | 237 | ```swift 238 | struct Composite { 239 | … 240 | func compose(other: Composite) -> Composite { 241 | return Composite(self, other) 242 | } 243 | } 244 | ``` 245 | 246 | 다음과 같이 작성할 수 있습니다: 247 | 248 | ```swift 249 | struct Composite { 250 | … 251 | func compose(other: Composite) -> Composite { 252 | return Composite(self, other) 253 | } 254 | } 255 | ``` 256 | 257 | _이유:_ 중복 타입 매개변수를 생략하려는 목적이 명확합니다. 그리고 반환 타입이 다른 타입 매개변수를 취할 때 명확하게 차이가 나도록 만듭니다. 258 | 259 | #### 연산자 정의에 공백 사용 [원문](https://github.com/github/swift-style-guide#use-whitespace-around-operator-definitions) 260 | 261 | 연산자를 정의할 때 공백을 사용합니다. 다음과 같이 하지 않습니다: 262 | 263 | ```swift 264 | func <|(lhs: Int, rhs: Int) -> Int 265 | func <|<(lhs: A, rhs: A) -> A 266 | ``` 267 | 268 | 다음과 같이 작성합니다: 269 | 270 | ```swift 271 | func <| (lhs: Int, rhs: Int) -> Int 272 | func <|< (lhs: A, rhs: A) -> A 273 | ``` 274 | 275 | _이유:_ 연산자는 문장부호로 되어 있으며, 타입 또는 값 매개 변수 목록과 붙어 있으면 읽기 어렵습니다. 공백이 추가되어 더 명확해집니다. 276 | 277 | #### 번역 278 | 279 | * [中文版](https://github.com/Artwalk/swift-style-guide/blob/master/README_CN.md) 280 | * [日本語版](https://github.com/jarinosuke/swift-style-guide/blob/master/README_JP.md) --------------------------------------------------------------------------------