Swift 类和对象
创建和使用类
Swift 使用class
创建一个类,类可以包含字段和方法:
1 class Shape {
2 var numberOfSides = 0
3 func simpleDescription () -> String {
4 return "A shape with \(numberOfSides) sides."
5 }
6 }
创建Shape
类的实例,并调用其字段和方法。
1 var shape = Shape ()
2 shape.numberOfSides = 7
3 var shapeDescription = shape.simpleDescription ()
通过init
构建对象,既可以使用self
显式引用成员字段(name
),也可以隐式引用(numberOfSides
)。
1 class NamedShape {
2 var numberOfSides: Int = 0 var name: String
3
4 init (name: String) {
5 self.name = name
6 }
7
8 func simpleDescription () -> String {
9 return "A shape with \(numberOfSides) sides."
10 }
11 }
使用deinit
进行清理工作。
继承和多态
Swift 支持继承和多态(override
父类方法):
1 class Square: NamedShape {
2 var sideLength: Double
3
4 init (sideLength: Double, name: String) {
5 self.sideLength = sideLength
6 super.init (name: name)
7 numberOfSides = 4
8 }
9
10 func area () -> Double {
11 return sideLength * sideLength
12 }
13
14 override func simpleDescription () -> String {
15 return "A square with sides of length \(sideLength)."
16 }
17 }
18 let test = Square (sideLength: 5.2, name: "my test square")
19 test.area ()
20 test.simpleDescription ()
注意:如果这里的simpleDescription
方法没有被标识为override
,则会引发编译错误。
属性
为了简化代码,Swift 引入了属性(property),见下面的perimeter
字段:
1 class EquilateralTriangle: NamedShape {
2 var sideLength: Double = 0.0
3
4 init (sideLength: Double, name: String) {
5 self.sideLength = sideLength
6 super.init (name: name)
7 numberOfSides = 3
8 }
9
10 var perimeter: Double {
11 get {
12 return 3.0 * sideLength
13 }
14 set {
15 sideLength = newValue / 3.0
16 }
17 }
18
19 override func simpleDescription () -> String {
20 return "An equilateral triagle with sides of length \(sideLength)."
21 }
22 }
23 var triangle = EquilateralTriangle (sideLength: 3.1, name: "a triangle")
24 triangle.perimeter
25 triangle.perimeter = 9.9
26 triangle.sideLength
注意:赋值器(setter)中,接收的值被自动命名为newValue
。
willSet 和 didSet
EquilateralTriangle
的构造器进行了如下操作:
- 为子类型的属性赋值。
- 调用父类型的构造器。
- 修改父类型的属性。
如果不需要计算属性的值,但需要在赋值前后进行一些操作的话,使用willSet
和didSet
:
1 class TriangleAndSquare {
2 var triangle: EquilateralTriangle {
3 willSet {
4 square.sideLength = newValue.sideLength
5 }
6 }
7 var square: Square {
8 willSet {
9 triangle.sideLength = newValue.sideLength
10 }
11 }
12 init (size: Double, name: String) {
13 square = Square (sideLength: size, name: name)
14 triangle = EquilateralTriangle (sideLength: size, name: name)
15 }
16 }
17 var triangleAndSquare = TriangleAndSquare (size: 10, name: "another test shape")
18 triangleAndSquare.square.sideLength
19 triangleAndSquare.square = Square (sideLength: 50, name: "larger square")
20 triangleAndSquare.triangle.sideLength
从而保证triangle
和square
拥有相等的sideLength
。
调用方法
Swift 中,函数的参数名称只能在函数内部使用,但方法的参数名称除了在内部使用外还可以在外部使用(第一个参数除外),例如:
1 class Counter {
2 var count: Int = 0
3 func incrementBy (amount: Int, numberOfTimes times: Int) {
4 count += amount * times
5 }
6 }
7 var counter = Counter ()
8 counter.incrementBy (2, numberOfTimes: 7)
注意 Swift 支持为方法参数取别名:在上面的代码里,numberOfTimes
面向外部,times
面向内部。
?的另一种用途
使用可空值时,?
可以出现在方法、属性或下标前面。如果?
前的值为nil
,那么?
后面的表达式会被忽略,而原表达式直接返回nil
,例如:
1 let optionalSquare: Square? = Square (sideLength: 2.5, name: "optional square") let sideLength = optionalSquare?.sideLength
当optionalSquare
为nil
时,sideLength
属性调用会被忽略。