Objects and Classes 对象和类
使用关键字 class 定义一个类,在定义类的属性的时候与常量或者变量的定义相同(继承父类的属性定义不同),方法和函数的定义也相同
class Shape { var numberOfSides = 0 func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } }
var shape = Shape() shape.numberOfSides = 7 var shapeDescription = shape.simpleDescription()
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的使用,相信用过OC的都知道self.name 和 name的区别吧,当实例声明的时候,每个属性都要赋初值,可以再声明的时候赋初值(类似numberOfSides)或者在构造的时候赋初值(类似name)
使用 deinit 在对象被销毁之前做一些清理操作,同OC中的 dealloc 函数
类的继承
使用冒号 : 进行继承,任何类不需要继承标准根类,如NSObject,可以根据需要包含或者省略一个超类
使用 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()
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") triangle.perimeter triangle.perimeter = 9.9 triangle.sideLength在 perimeter 的 set 方法中有一个没有声明的 newValue ,接收的值被自动命名为 newValue ,比如上文中的 9.9
上面的构造器中进行以下三个步骤:
1. 为子类的属性赋值
2. 调用父类的构造器
3. 修改父类中定义的属性的值
使用WillSet 和 DidSet 在 setter 一个 newValue 之前和之后执行
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") triangleAndSquare.square.sideLength triangleAndSquare.triangle.sideLength triangleAndSquare.square = Square(sideLength: 50, name: "larger square") triangleAndSquare.triangle.sideLength保证了三角形和正方形的边长一样
函数的参数只能在函数的内部使用,但是方法的参数名称除了在内部使用还可以在外部使用(第一个参数除外)
class Counter { var count: Int = 0 func incrementBy(amount: Int, numberOfTimes times: Int) { count += amount * times } } var counter = Counter() counter.incrementBy(2, numberOfTimes: 7)上面代码中 numberOfTimes是别名,可以在外面使用
?的另外一种用途
如果实例的值为 nil ,那么所有调用这个实例的语句都不会起作用
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") let sideLength = optionalSquare?.sideLength
下一节说枚举和结构