使用class
和類名來建立一個類。類中屬性的聲明和常量、變量聲明同樣,惟一的區別就是它們的上下文是類。一樣,方法和函數聲明也同樣。javascript
class Shape { var numberOfSides = 0 func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } }
練習: 使用
let
添加一個常量屬性,再添加一個接收一個參數的方法。php
要建立一個類的實例,在類名後面加上括號。使用點語法來訪問實例的屬性和方法。java
var shape = Shape() shape.numberOfSides = 7 var shapeDescription = shape.simpleDescription()
這個版本的Shape
類缺乏了一些重要的東西:一個構造函數來初始化類實例。使用init
來建立一個構造器。swift
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
被用來區別實例變量。當你建立實例的時候,像傳入函數參數同樣給類傳入構造器的參數。每一個屬性都須要賦值——不管是經過聲明(就像numberOfSides
)仍是經過構造器(就像name
)。ide
若是你須要在刪除對象以前進行一些清理工做,使用deinit
建立一個析構函數。函數
子類的定義方法是在它們的類名後面加上父類的名字,用冒號分割。建立類的時候並不須要一個標準的根類,因此你能夠忽略父類。ui
子類若是要重寫父類的方法的話,須要用override
標記——若是沒有添加override
就重寫父類方法的話編譯器會報錯。編譯器一樣會檢測override
標記的方法是否確實在父類中。spa
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
,構造器接收兩個參數,一個是半徑一個是名稱,在子類Circle
中實現area()
和simpleDescription()
方法。code
除了儲存簡單的屬性以外,屬性能夠有 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 triagle with sides of length \(sideLength)." } } var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle") print(triangle.perimeter) triangle.perimeter = 9.9 print(triangle.sideLength)
在perimeter
的 setter 中,新值的名字是newValue
。你能夠在set
以後顯式的設置一個名字。
注意EquilateralTriangle
類的構造器執行了三步:
若是你不須要計算屬性,可是仍然須要在設置一個新值以前或者以後運行代碼,使用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") print(triangleAndSquare.square.sideLength) print(triangleAndSquare.triangle.sideLength) triangleAndSquare.square = Square(sideLength: 50, name: "larger square") print(triangleAndSquare.triangle.sideLength)
處理變量的可選值時,你能夠在操做(好比方法、屬性和子腳本)以前加?
。若是?
以前的值是nil
,?
後面的東西都會被忽略,而且整個表達式返回nil
。不然,?
以後的東西都會被運行。在這兩種狀況下,整個表達式的值也是一個可選值。
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") let sideLength = optionalSquare?.sideLength