標籤:swift
要定義一個類,只要在 class 後面加上類名即可。在類中定義屬性的寫法與定義常量和變數一樣,只不過它是在類的範圍裡。同樣,方法的定義和函數定義是一樣的寫法。
class Shape { var numberOfSides = 0 func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." }}
試一試
用 let 增加一個常量屬性,再加一個有一個參數的方法。
要建立類的執行個體,只需在類名後加上括弧就可以了。用句點來訪問類執行個體的屬性和方法。
var shape = Shape()shape.numberOfSides = 7var shapeDescription = shape.simpleDescription()
這個版本的Shape類還差了點重要的東西:初始化器(博主註:其實就是建構函式),用來在類執行個體建立時構建該類。用 init 來表示。
class NamedShape { var numberOfSides: Int = 0 var name: String init(name: String) { self.name = name } func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." }}
注意 self 是怎麼用來把name參數傳給name屬性的。建立類執行個體時,參數就像調用函數時傳參數那樣傳給初始化器。每個屬性都需要指定一個值——不管是在定義時(就像numberOfSides)還是在初始化器裡(就像name)。
如果要在對象被釋放之前做一些清理工作,可以用 deinit 來建立一個解構函式。
要定義子類只需在類名後加分號,再寫上父類的類名即可。Swift裡並不要求類必須繼承任何標準的父類,所以如果需要的話可以省略掉父類。
子類要重寫父類的方法需要用 override 進行標記——如果沒加override就重寫了父類的方法是會被編譯器報錯的。編譯器還會檢測加了override的方法是不是真的是重寫父類的方法。
class Square: NamedShape { var sideLength: Double init(sideLength: Double, name: String) { self.sideLength = sideLength super.init(name: name) numberOfSides = 4 } func area() -> Double { return sideLength * sideLength } override func simpleDescription() -> String { return "A square with sides of length \(sideLength)." }}let test = Square(sideLength: 5.2, name: "my test square")test.area()test.simpleDescription()
試一試
加一個NamedShape的子類Circle,有radius屬性,並且在初始化器中接收該參數。在Circle類裡實現一個area() 和 simpleDescription() 方法。
除了簡單儲存值外,屬性還可以加getter和setter。
class EquilateralTriangle: NamedShape { var sideLength: Double = 0.0 init(sideLength: Double, name: String) { self.sideLength = sideLength super.init(name: name) numberOfSides = 3 } var perimeter: Double { get { return 3.0 * sideLength } set { sideLength = newValue / 3.0 } } override func simpleDescription() -> String { return "An equilateral triangle with sides of length \(sideLength)." }}var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")println(triangle.perimeter)triangle.perimeter = 9.9println(triangle.sideLength)
在周長的setter裡,新的值有個被隱式的稱為newValue的名字。你可以在set後面加個括弧,顯式地定義一個名字。
注意 EquilateralTriangle 類的初始化器有三步不同:
設定子類定義的屬性值。
調用父類的初始化器。
更改父類定義的屬性值。
其餘要用到方法、getter或者setter的初始化工作也可以在這個時候進行。
如果不需要計算屬性值但任然要在設定了新值之前或之後運行一段代碼的話,就要用到 willSet 和 didSet。例如,下面的類確保了三角形的邊長與正方形邊長是一致的。
class TriangleAndSquare { var triangle: EquilateralTriangle { willSet { square.sideLength = newValue.sideLength } } var square: Square { willSet { triangle.sideLength = newValue.sideLength } } init(size: Double, name: String) { square = Square(sideLength: size, name: name) triangle = EquilateralTriangle(sideLength: size, name: name) }}var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")println(triangleAndSquare.square.sideLength)println(triangleAndSquare.triangle.sideLength)triangleAndSquare.square = Square(sideLength: 50, name: "larger square")println(triangleAndSquare.triangle.sideLength)
類裡的方法與函數有一個很重要的不同。函數裡的參數名只能用於函數內,但方法裡的參數名還可以用在你調用該方法的時候(除了第一個參數)。預設情況下,方法調用時與方法自己內部,參數名是一樣的。你可以再指定另一個名字,用於方法內。
class Counter { var count: Int = 0 func incrementBy(amount: Int, numberOfTimes times: Int) { count += amount * times }}var counter = Counter()counter.incrementBy(2, numberOfTimes: 7)
遇到可選值的時候,你可以在方法、屬性和下標等操作前寫個 ?。如果 ?前的值是 nil ,那麼 ? 後的所有東西都會被忽略,而且整個運算式的值是nil。否則,可選值被開啟,?後的所有東西按照開啟值來繼續。不管哪種情況,整個運算式的值都是可選值。
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")let sideLength = optionalSquare?.sideLength
Swift之旅(四)對象和類