Swift学习笔记三-对象和类

Swift有很多高级特性,个人感觉Swift在语法跟数据结构上比Java要高级好多.

声明类

1
2
3
4
5
6
7
8
9
10
11
12
import Foundation
//使用class和类名创建一个类.类中属性的声明和常量,变量声明一样,唯一的区别就是它们的上下文是类.同样,方法同函数声明也一样.
class Shape {
var numberOfSides = 0
let maxNumber = 0
func simpleDescripe() -> String {
return "A shape with \(numberOfSides) sides"
}
func calMaxNumber(number:Int) -> String {
return "The max number is \(number)"
}
}

实例化类并访问属性调用方法

1
2
3
4
//要创建一个类的实例,在类名后面加上括号,用点语法访问属性和方法
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescripe()

创建构造器(构造方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
//上面的类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"
}
}
//注意self是用来区别实例变量的.当创建实例的时候,像给函数传入参数一样一样给类的构造函数传入函数,每个属性都需要被赋值,不然会报错--无论是通过声明(像numberOfSides)还是通过构造函数(就像name)
//如果需要在删除对象之前进行清理操作,使用deinit创建一个析构函数

继承父类重写方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//子类的定义方法是在他们的类名后面加上父类的名字,用冒号分隔.创建类的时候并不需要一个标准的根类,所以可以忽略父类.
//子类如果要重写父类的方法,需要用override标记.如果没用标记就重写父类方法编译器会报错.编译器同样会检测override标记的方法是否确实在父类中.
class Sequare: 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 is \(sideLength)"
}
}
let sequare = Sequare(sideLength: 5.0, name: "xiaoming")
sequare.area()
sequare.simpleDescription()

//练习: 创建NamedShape的另一个子类Circle,构造器接收两个参数,一个是半径一个是名称,在子类Circle中实现area()和simpleDescription()方法。
class Circle:NamedShape {
var radius:Double
init(radius: Double, name: String) {
self.radius = radius
super.init(name: name)
}

func area() -> Double {
return radius * radius * 3.14
}

override func simpleDescription() -> String {
return "A circle with radius of length is \(radius)"
}
}

属性的setter和getter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//除了存储简单的属性之外,属性还可以有getter方法和setter方法
//在swift中使用get/set 主要是用来间接获取/改变其他属性的值。在swift中这类属性被称之为“计算属性” ,不要拿其他面向对象语言跟Swift作对比(尤其是Java,OC,Java中的setter跟getter方法就是操作本属性)
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
}
// set(value) {
// sideLength = value / 3.0
// }
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
print(triangle.perimeter)
triangle.perimeter = 9.9
print(triangle.sideLength)
//在perimeter的setter中,新值的名字是newValue.可以在set之后显式设置一个名字.
//注意:EquilateralTriangle类的构造器执行了三步:
//1.设置子类声明的属性值
//2.调用子类构造器
//3.改变父类定义的属性值.其他的工作比如调用方法,getters和setters也可以在这个阶段完成.

属性监视willSet跟didSet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//如果不需要计算属性,但是仍然需要在设置一个新值之前或者之后运行代码,使用willSet或者didSet.willSet跟didSet用来监视除初始化之外的属性值的变化.当这个值变化之前做点什么别的事,变化之后做点什么别的事.
//比如,下面的了确保三角形的变成总是和正方形的变成相同
class TriangleAndSquare {

var triangle: EquilateralTriangle {
willSet {
sequare.sideLength = newValue.sideLength
}
// willSet(value) {
// print("willSet")
// sequare.sideLength = value.sideLength
// }
}

var sequare: Sequare {
willSet {
triangle.sideLength = newValue.sideLength
}
}

init(size: Double, name: String) {
sequare = Sequare(sideLength: size, name: name)
triangle = EquilateralTriangle(sideLength: size, name: name)
}
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "Another test sequare")
print(triangleAndSquare.sequare.sideLength)
print(triangleAndSquare.triangle.sideLength)
triangleAndSquare.sequare = Sequare(sideLength: 50, name: "larger sequare")//只有这句才能调用willSet,初始化不调用
print(triangleAndSquare.triangle.sideLength)

处理可选值

1
2
3
4
//处理变量的可选值时,可以在操作(比如属性,方法,子脚本)之前加?.如果?之前的值是nil,则?后面的内容会被忽略,并且整个表达式返回nil.否则?之后的内容都会被执行.这两种情况下整个表达式也是一个可选值
let optionalSquare: Sequare? = Sequare(sideLength: 20, name: "optional")
let sideLength = optionalSquare?.sideLength
print(sideLength!)

–EOF–