標籤:
1.建立和使用類
使用 class 和類名來建立一個類。類中屬性的聲明和常量、變數聲明一樣,唯一的區別就是 它們的上下文是類。同樣,方法和函式宣告也一樣。
class Shape { var numberOfSides = 0 func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." }}
建立Shape類的執行個體,並調用其欄位和方法。
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." }}
注意:通過init構建對象,既可以使用self顯式引用成員欄位(name),也可以隱式引用(numberOfSides)。
如果你需要在刪除對象之前進行一些清理工作,使用 deinit 建立一個解構函式進行清理。
2.繼承和多態
子類的定義方法是在它們的類名後面加上父類的名字,用冒號分割。建立類的時候並不需要 一個標準的根類,所以你可以忽略父類。
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()
為了簡化代碼,Swift引入了屬性(property),見下面的perimeter欄位:
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 triagle with sides of length \(sideLength)." }}var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")triangle.perimetertriangle.perimeter = 9.9triangle.sideLength
注意:賦值器(setter)中,接收的值被自動命名為newValue。你可以在 set 之後顯示的設定一個名 字。
3.willSet和didSet
注意 EquilateralTriangle 類的構造器執行了三步:
1. 設定子類聲明的屬性值
2. 調用父類的構造器
3. 改變父類定義的屬性值。其他的工作比如調用方法、getters 和 setters 也可以在這個階段完成。
如果你不需要計算屬性但是需要在設定一個新值之前運行一些代碼,使用 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")triangleAndSquare.square.sideLengthtriangleAndSquare.square = Square(sideLength: 50, name: "larger square")triangleAndSquare.triangle.sideLengt
比如,上面的類確保三角形的邊長總是和正方形的邊長相同
4.調用方法
Swift中,函數的參數名稱只能在函數內部使用,但方法的參數名稱除了在內部使用外還可以在外部使用(第一個參數除外),例如:
class Counter { var count: Int = 0 func incrementBy(amount: Int, numberOfTimes times: Int) { count += amount * times }}var counter = Counter()counter.incrementBy(2, numberOfTimes: 7)
//注意Swift支援為方法參數取別名:在上面的代碼裡,numberOfTimes面向外部,times面向內部。
5.?的另一種用途
使用可空值時,?可以出現在方法、屬性或下標前面。如果?前的值為nil,那麼?後面的運算式會被忽略,而原運算式直接返回nil,例如:
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")let sideLength = optionalSquare?.sideLength
//當optionalSquare為nil時,sideLength屬性調用會被忽略。
6.補充
初始化:
init關鍵詞,和OC一樣。不過這塊非常像CPP,如下面這東西
class nyan{ var num: Int = 1024 init() { num = 1; } } class miao:nyan { var num1: Int = 1
override init() {
num1 = 2 } } var a = miao() println(a.num) println(a.num1)
//如果以OC的思維來看,它輸出的應該是 1024, 2。因為OC只要沒有call super,就是覆蓋掉了。
//但實際上Swift輸出的是 1, 2。倘若,我們在兩個init加上打log的話,會發現,子類的init先運行,然後運行父類的。那麼什麼時候在子類的init裡面call super.init()呢?
顯而易見:當在子類裡面要調用父類的成員變數時,要先調用super.init()去初始化它,若沒有寫的話,XCode會報編譯錯誤。
Swift學習3---類和對象