使用“class”和類名來創(chuàng)建一個類悯辙。類中屬性的聲明和常量迎吵、變量聲明一樣击费,唯一的區(qū)別就是它們的上下文是類。同樣蔫巩,方法和函數(shù)聲明也一樣。
class Shape {
? var numberOfSides = 0
? func simpleDescription() -> String {
? ? return "A shape with \(numberOfSides) sides."
? }
}
要創(chuàng)建一個類的實例垃瞧,在類名后面加上括號坪郭。使用點語法來訪問實例的屬性和方法。
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
這個版本的Shape類缺少了一些重要的東西:一個構(gòu)造函數(shù)來初始化類實例嗦锐。使用“init”來創(chuàng)建一個構(gòu)造器沪曙。
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”被用來區(qū)別實例變量。當(dāng)你創(chuàng)建實例的時候菊值,像傳入函數(shù)參數(shù)一樣給類傳入構(gòu)造器的參數(shù)育灸。每個屬性都需要賦值——無論是通過聲明(就像“numberOfSides”)還是通過構(gòu)造器(就像“name”)。
如果你需要在刪除對象之前進(jìn)行一些清理工作儿子,使用“deinit”創(chuàng)建一個析構(gòu)函數(shù)砸喻。
子類的定義方法是在它們的類名后面加上父類的名字蒋譬,用冒號分割愉适。創(chuàng)建類的時候并不需要一個標(biāo)準(zhǔn)的根類维咸,所以你可以忽略父類。
子類如果要重寫父類的方法的話癌蓖,需要用“override”標(biāo)記——如果沒有添加“override”就重寫父類方法的話編譯器會報錯。編譯器同樣會檢測“override”標(biāo)記的方法是否確實在父類中坐慰。
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()
除了儲存簡單的屬性之外结胀,屬性可以有“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”之后顯式的設(shè)置一個名字。
注意“EquilateralTriangle”類的構(gòu)造器執(zhí)行了三步:
1. 設(shè)置子類聲明的屬性值
2. 調(diào)用父類的構(gòu)造器
3. 改變父類定義的屬性值健芭。其他的工作比如調(diào)用方法、getters 和 setters 也可以在這個階段完成若贮。
如果你不需要計算屬性痒留,但是仍然需要在設(shè)置一個新值之前或者之后運行代碼,使用“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”原茅,“?”后面的東西都會被忽略堕仔,并且整個表達(dá)式返回“nil”。否則摩骨,“?”之后的東西都會被運行恼五。在這兩種情況下,整個表達(dá)式的值也是一個可選值灾馒。
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength