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()
创建构造函数 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的使用,相信用过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()
为属性添加 getter 和 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 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
下一节说枚举和结构