1.创建和使用类
使用 class 和类名来创建一个类。类中属性的声明和常量、变量声明一样,唯一的区别就是 它们的上下文是类。同样,方法和函数声明也一样。
class Shape { var numberOfSides = 0 func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } }
创建Shape类的实例,并调用其字段和方法。
var shape = Shape() shape.numberOfSides = 7 var shapeDescription = shape.simpleDescription()
这个版本的 Shape 类缺少了一些重要的东西:一个构造函数来初始化类实例。使用 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." } }
注意:通过init构建对象,既可以使用self显式引用成员字段(name),也可以隐式引用(numberOfSides)。
如果你需要在删除对象之前进行一些清理工作,使用 deinit 创建一个析构函数进行清理。
2.继承和多态
子类的定义方法是在它们的类名后面加上父类的名字,用冒号分割。创建类的时候并不需要 一个标准的根类,所以你可以忽略父类。
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()
为了简化代码,Swift引入了属性(property),见下面的perimeter字段:
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
注意:赋值器(setter)中,接收的值被自动命名为newValue。你可以在 set 之后显示的设置一个名 字。
3.willSet和didSet
注意 EquilateralTriangle 类的构造器执行了三步:
1. 设置子类声明的属性值
2. 调用父类的构造器
3. 改变父类定义的属性值。其他的工作比如调用方法、getters 和 setters 也可以在这个阶
段完成。
如果你不需要计算属性但是需要在设置一个新值之前运行一些代码,使用 willSet 和 didSet。
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.square = Square(sideLength: 50, name: "larger square") triangleAndSquare.triangle.sideLengt
比如,上面的类确保三角形的边长总是和正方形的边长相同
4.调用方法
Swift中,函数的参数名称只能在函数内部使用,但方法的参数名称除了在内部使用外还可以在外部使用(第一个参数除外),例如:
class Counter { var count: Int = 0 func incrementBy(amount: Int, numberOfTimes times: Int) { count += amount * times } } var counter = Counter() counter.incrementBy(2, numberOfTimes: 7)//注意Swift支持为方法参数取别名:在上面的代码里,numberOfTimes面向外部,times面向内部。
5.?的另一种用途
使用可空值时,?可以出现在方法、属性或下标前面。如果?前的值为nil,那么?后面的表达式会被忽略,而原表达式直接返回nil,例如:
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") let sideLength = optionalSquare?.sideLength//当optionalSquare为nil时,sideLength属性调用会被忽略。
6.补充
初始化:
init关键词,和OC一样。不过这块非常像CPP,如下面这东西
class nyan{ var num: Int = 1024 init() { num = 1; } } class miao:nyan { var num1: Int = 1
override init() {
num1 = 2 } } var a = miao() println(a.num) println(a.num1) //如果以OC的思维来看,它输出的应该是 1024, 2。因为OC只要没有call super,就是覆盖掉了。//但实际上Swift输出的是 1, 2。倘若,我们在两个init加上打log的话,会发现,子类的init先运行,然后运行父类的。那么什么时候在子类的init里面call super.init()呢?显而易见:当在子类里面要调用父类的成员变量时,要先调用super.init()去初始化它,若没有写的话,XCode会报编译错误。