用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類沒有在創(chuàng)建實例的時候初始化屬性。添加一個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是如何區(qū)別參數(shù)name和屬性name的。當你創(chuàng)建一個實例時像函數(shù)的調(diào)用的方法一樣傳入構(gòu)造器參數(shù)。每一個屬性都需要賦值=要么在聲明(numberOfSides)的時候,要么在初始化時(name)。
在這個對象銷毀前用deinit(看這個名字就知道是init的反義詞)折構(gòu)函數(shù)做一些清理操作。
子類要繼承父類,在子類名稱后面加上分號:。 沒有要求類必須繼承一個標準根類,所以你可以忽略根類。
子類可以重寫父類聲明的方法,即在方法前加上 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()
除了存儲一些簡單的屬性,類還可以定義一些計算屬性,計算屬性不直接存儲值,而是通過getter和setter,間接提取和設(shè)定值。
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")
print(triangle.perimeter)
triangle.perimeter = 9.9
print(triangle.sideLength)
在perimeter的setter中,參數(shù)被隱含地命名為newValue。你也可以將參數(shù)名字在set后面用括號括起來。
var perimeter: Double {
get {
return 3.0 * sideLength
}
set { (newValue)
sideLength = newValue / 3.0
}
}
注意EquilateralTriangle的構(gòu)造器有三個步驟
- 給當前類聲明的屬性賦值
- 調(diào)用父類的構(gòu)造器
- 改變父類定義的屬性。其他工作比如調(diào)用方法,getter,setter也可以在這里完成。
如果你不需要一個計算屬性但是仍然想在代碼運行前后設(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)
當處理可選類型,你可以在方法屬性和subscripting 前面加上問號?。如果?號前面的值是nil,那么問號后面的所有值都是nil.否則,?之后的所有代碼都會運行。在這兩種情況下,整個表達式的值是可選類型的。
let optionalSquare :Square? = Square(sideLength:2.5, name:"optional square")
let sideLength = optionalSquare?.sideLength