1. 程式人生 > >Apple Swift程式語言入門教程(轉)

Apple Swift程式語言入門教程(轉)

6   物件與類

使用 class 可以建立一個類。一個屬性的宣告則是在類裡作為常量或變數宣告的,除了是在類的上下文中。方法和函式也是這麼寫的。

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

Note

練習

通過 "let" 新增一個常量屬性,以及新增另一個方法能接受引數。

通過在類名後加小括號來建立類的例項。使用點語法來訪問例項的屬性和方法。

var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

這個版本的 Shape 類有些重要的東西不在:一個構造器來在建立例項時設定類。使用 init 來建立一個。

class NamedShape {
    var numberOfSides: Int = 0
    var name: String

    init(name: String) {
        self.name = name
    }   //by gashero

    func simpleDescription() -> String {
        return "A Shape with \(numberOfSides) sides."
    }
}

注意 self

 用來區分 name 屬性和 name 引數。構造器的生命跟函式一樣,除了會建立類的例項。每個屬性都需要賦值,無論在聲明裡還是在構造器裡。

使用 deinit 來建立一個析構器,來執行物件銷燬時的清理工作。

子類包括其超類的名字,以冒號分隔。在繼承標準根類時無需宣告,所以你可以忽略超類。

子類的方法可以通過標記 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()

Note

練習

編寫另一個 NamedShape 的子類叫做 Circle ,接受半徑和名字到其構造器。實現 area 和 describe 方法。

屬性可以有 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")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength

在 perimeter 的 setter 中,新的值的名字就是 newValue 。你可以提供一個在 set 之後提供一個不衝突的名字。

注意 EquilateralTriangle 的構造器有3個不同的步驟:

  1. 設定屬性的值
  2. 呼叫超類的構造器
  3. 改變超類定義的屬性的值,新增附加的工作來使用方法、getter、setter也可以在這裡

如果你不需要計算屬性,但是仍然要提供在設定值之後執行工作,使用 willSet 和 didSet 。例如,下面的類要保證其三角的邊長等於矩形的變長。

class TriangleAndSquare {
    var triangle: EquilaterTriangle {
    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 = EquilaterTriangle(sideLength: size, name: name)
    }
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
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