首页 > 代码库 > Swift 类和对象

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的构造器进行了如下操作:

  1. 为子类型的属性赋值。
  2. 调用父类型的构造器。
  3. 修改父类型的属性。

  如果不需要计算属性的值,但需要在赋值前后进行一些操作的话,使用willSetdidSet

 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

从而保证trianglesquare拥有相等的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

optionalSquarenil时,sideLength属性调用会被忽略。