Swift中使用class
关键字定义类。类里面属性的声明与定义变量和常量差不多,而成员方法也与普通函数的写法一样,只是写在类里面。
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
试验
给上面的类用let
添加一个常量属性,并且增加一个能够接受一个参数的方法
直接在类名后增加圆括号就可以创建这个类的实例,然后通过点操作符访问它的属性和成员方法。
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
不过上面的Shape
类还缺少一些重要的东西:在创建对象的时候进行初始化的初始化器。初始化器用init
进行定义。
class NameShape {
var numberOfSides: Int = 0
var name: String
init(name: String) {
self.name = name
}
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
这里要注意的是init
方法中self
的用法。初始化方法的参数传递与普通的函数类似。类中的属性都应该进行初始化赋值,不管是在声明的时候还是在初始化器中。
deinit
是Swift的析构函数,与dealloc
类似,用在对象销毁时进行清理工作。
在类名后使用冒号:
和父类的名字表示继承关系,Swift中并不要求每个类都有父类。
子类使用override
关键字来重写父类的方法,如果没有写override
的话,会出现编译器错误。同样,编译器也会检查带有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()
试验
为NamedShape
创建一个叫Circle
的子类,使它能够接受一个半径和名字作为参数。然后实现area
和describe
方法。
与Objective-C类似,Swift还能给属性定义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 triangle with sides of length \(sideLength)."
}
}
var triangle = EquilateralTraingle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength
在perimeter
的设置方法中,新的值默认存放在newValue
变量里。当然,也可以显式的在set
方法后的圆括号中提供变量名字。
注意EquilateralTriangle
类的初始化器里有三步:
设置子类中定义的属性的值。
调用父类的初始化器
改变父类中定义的属性的值。
如果你不需要计算属性的值,但是想要在属性的值发生改变之前或者改变后执行一些任务,可以使用willSet
和didSet
。例如下面的代码可以保证三角形和四边形的边长总是相同的。
class TriangleAndSquare {
var triangle: EquilateralTraingle {
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 = EuilateralTriangle(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.imcrementBy(2, numberOfTimes: 7)
使用选项(Optional)的时候,可以在方法、属性等操作符前使用?
。如果选项的值为nil
则忽略执行?
后的表达式,并且整个表达式的值为nil
。否则就执行?
后的表达式。
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optinal square")
let sideLength = optionalSquare?.sideLength