## 類和結構體(Classes and Structures)
### 選擇使用誰?(Which one to use?)
請記住,結構體是[值類型](https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-XID_144)。使用結構體并沒有一個標識。一個數組包含`[a, b, c]`和另外一個數組同樣包含`[a, b, c]`是完全一樣的,它們完全可以交換使用。使用第一個還是使用第二個無關緊要,因為它們代表的是同一個東西。這就是為什么數組是結構體。
類是[引用類型](https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-XID_145)。使用類是有一個標識或者有一個特定的生命周期。你需要對一個人類建模為一個類,因為兩個不同的人的實例,是兩個不同的東西。只是因為兩個人有同樣的名字和生日,也不能斷定這兩個人是一樣的。但是人的生日是一個結構體,因為日期1950-3-3和另外一個日期1950-3-3是相同的。日期不需要一個標識。
有時,一些事物應該定義為結構體,但是需要兼容AnyObject或者已經在以前的歷史版本中定義為類(`NSDate`,`NSSet`)。盡可能的嘗試遵守這些規則。
### 定義的案例(Example definition)
以下是一個風格很好的類定義:
~~~
class Circle: Shape {
var x: Int, y: Int
var radius: Double
var diameter: Double {
get {
return radius * 2
}
set {
radius = newValue / 2
}
}
init(x: Int, y: Int, radius: Double) {
self.x = x
self.y = y
self.radius = radius
}
convenience init(x: Int, y: Int, diameter: Double) {
self.init(x: x, y: y, radius: diameter / 2)
}
func describe() -> String {
return "I am a circle at \(centerString()) with an area of \(computeArea())"
}
override func computeArea() -> Double {
return M_PI * radius * radius
}
private func centerString() -> String {
return "(\(x),\(y))"
}
}
~~~
以上例子遵循了以下風格規范:
* 指定屬性,變量,常量,參數定義或者其他定義的類型,在冒號后面,緊跟著一個空格,而不是把空格放在冒號前面。比如:`x: Int`和`Circle: Shape`。
* 如果能表示相同的目的和上下文,可以在同一行定義多個變量和結構體。
* 縮進getter,setter的定義和屬性觀察器的定義。
* 不需要添加`internal`這樣的默認的修飾符。同樣的,不需要在重寫一個方法時添加訪問修飾符。
### Self的使用(Use of Self)
為了保持簡潔,避免使用 self 關鍵詞,Swift 不需要使用?`self`?來訪問對象屬性和調用對象方法。
必須使用?`self`?來區分構造器中屬性命名和參數命名,還有在閉包表達式中引用屬性值(編譯器需要區分):
~~~
class BoardLocation {
let row: Int, column: Int
init(row: Int, column: Int) {
self.row = row
self.column = column
let closure = {
println(self.row)
}
}
}
~~~
### 協議遵守(Protocol Conformance)
當我們對一個類添加協議時,推薦使用一個單獨的類擴展來實現協議的方法。這可以保持協議相關的方法聚合在一起,同時也可以簡單的標識出一個協議對應類中需要實現哪些對應的方法。
同時,別忘了添加// MARK:,注釋可以使得代碼組織的更好!
推薦做法:
~~~
class MyViewcontroller: UIViewController {
// class stuff here
}
// MARK: - UITableViewDataSource
extension MyViewcontroller: UITableViewDataSource {
// table view data source methods
}
// MARK: - UIScrollViewDelegate
extension MyViewcontroller: UIScrollViewDelegate {
// scroll view delegate methods
}
~~~
不推薦做法:
~~~
class MyViewcontroller: UIViewController, UITableViewDataSource, UIScrollViewDelegate {
// all methods
}
~~~
### 計算屬性(Computed Properties)
為了保持簡潔,如果一個計算屬性是只讀的,請忽略掉get語句。只有在需要定義set語句的時候,才提供get語句。
推薦做法:
~~~
var diameter: Double {
return radius * 2
}
~~~
不推薦做法:
~~~
var diameter: Double {
get {
return radius * 2
}
}
~~~