使用class
來(lái)創(chuàng)建一個(gè)類(lèi),類(lèi)的名稱附加在class
之后您单。類(lèi)中的屬性聲明和普通的常量和變量的聲明一樣斋荞,除非是在類(lèi)的上下文中。方法和函數(shù)也是這么寫(xiě)虐秦。
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape With \(numberOfSides) sides."
}
}
練習(xí):使用let
增加一個(gè)常量平酿,并且增加一個(gè)帶參數(shù)的函數(shù)。
class Shape {
var numberOfSides = 0
let shapeWidth = 45.0
func simpleDescription() -> String {
return "A shape With \(numberOfSides) sides."
}
func shapeWidthAndHeight(height: Float) -> String {
return "The shape's width is \(shapeWidth), height is \(height)."
}
}
通過(guò)在類(lèi)名后添加圓括號(hào)來(lái)實(shí)例化悦陋。使用.
來(lái)訪問(wèn)實(shí)例屬性和方法蜈彼。
var oneShape = Shape()
oneShape.numberOfSides = 3
oneShape.simpleDescription()
這個(gè)版本的Shape
類(lèi)遺漏了一個(gè)重要的事情:用于在創(chuàng)建實(shí)例時(shí)設(shè)置類(lèi)的構(gòu)造器。使用init
來(lái)創(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."
}
}
注意上面的代碼是如何通過(guò)self
來(lái)區(qū)分name
屬性和構(gòu)造器的name
參數(shù)幸逆。構(gòu)造器的參數(shù)如同調(diào)用函數(shù)一樣,在實(shí)例化類(lèi)的時(shí)候傳入進(jìn)來(lái)。所有屬性都需要被賦值——可以在屬性聲明的時(shí)候(如numberOfSides
)或者在構(gòu)造器里(如name
)進(jìn)行賦值还绘。
使用deinit
來(lái)創(chuàng)建一個(gè)析構(gòu)器楚昭,在對(duì)象銷(xiāo)毀之前做一些清理工作。
創(chuàng)建子類(lèi)時(shí)拍顷,名稱后面跟著超類(lèi)的名字抚太,中間用冒號(hào)分割。Swift沒(méi)有要求創(chuàng)建的類(lèi)要集成任何標(biāo)準(zhǔn)根類(lèi)昔案,所以你可以在需要的情況下引入或者忽略超類(lèi)尿贫。
子類(lèi)中的方法可以通過(guò)標(biāo)記override
來(lái)覆蓋超類(lèi)中的實(shí)現(xiàn),沒(méi)有override
爱沟,編譯器會(huì)視為錯(cuò)誤帅霜。編譯器同時(shí)也會(huì)檢查那些帶著override
卻沒(méi)有覆蓋任何超類(lèi)方法的子類(lèi)方法。
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()
練習(xí):創(chuàng)建另外一個(gè)NamedShape
的子類(lèi)Circle
呼伸,并未其構(gòu)造器添加半徑和名稱參數(shù)。并且為Circle
類(lèi)添加area
和simpleDescription
兩個(gè)方法钝尸。
class Circle: NamedShape {
var radius: Double
init(radius: Double, name: String) {
self.radius = radius
super.init(name: name)
}
func area() -> Double {
return M_PI * radius * radius
}
override func simpleDescription() -> String {
return "A circle with radius \(radius)."
}
}
除了保存簡(jiǎn)單的屬性括享,屬性還有一個(gè)getter和一個(gè)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")
var perimeter = triangle.perimeter
print(triangle.perimeter)
triangle.perimeter = 9.9
print(triangle.sideLength)
在perimeter
的setter中珍促,新值的有一個(gè)隱式的名字就是newValue
铃辖,你可以在set
后面緊跟上一對(duì)圓括號(hào),并顯式指定一個(gè)不沖突的名字放在圓括號(hào)中猪叙。
注意娇斩,EquilateralTriangle
的構(gòu)造器執(zhí)行了三個(gè)操作:
設(shè)置了子類(lèi)聲明的屬性的值。
調(diào)用超類(lèi)的構(gòu)造器穴翩。
改變超類(lèi)定義的屬性的值犬第。所有附加的初始化工作(使用方法,getter或者setter)都可以在這個(gè)點(diǎn)完成芒帕。
如果你不需要對(duì)屬性進(jìn)行計(jì)算但是仍然需要提供在設(shè)置新值時(shí)的前置和后置的運(yùn)行代碼歉嗓,可以使用willSet
和didSet
。例如背蟆,如下的類(lèi)要保證三角的邊長(zhǎng)和矩形的邊長(zhǎng)相等鉴分。
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)
當(dāng)處理可選值的時(shí)候,你可以在操作(比如方法带膀、屬性和下標(biāo))之前,添加?
志珍。如果?
前面的值是nil
,?
后的所有東西將被忽略垛叨,整個(gè)表達(dá)式的值為nil
伦糯。另外,可選值是未包裝的,所有?
后面的操作都會(huì)運(yùn)用在未包裝的值上舔株。在兩種情況中莺琳,整個(gè)表達(dá)式的值是一個(gè)可選值。
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength