Swift中文教程(五)--对象和类

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

Class 类

在Swift中可以用class关键字后跟类名创建一个类。在类里,一个属性的声明写法同一个常量或变量的声明写法一样,除非这个属性是在类的上下文里面,否则,方法和函数的写法也是这样:

1classShape {2var numberOfSides =03func simpleDescription() ->String {4return"A shape with \(numberOfSides) sides."5}6}

练习:

用let关键字添加一个常量属性,添加另一个方法用来接收参数。

在类名后面加小括号来创建类的实例化,使用.(点号连接符)来访问实例的方法和属性:

1var shape =Shape()2shape.numberOfSides = 73var shapeDescription = shape.simpleDescription()

这个版本的Shape类缺少一个重要的东西:构造器--类被创建后的设置。可以使用init来创建一个:

1classNamedShape {2var numberOfSides: Int =03var name: String45init(name: String) {6self.name =name7}89func simpleDescription() ->String {10return"A shape with \(numberOfSides) sides."11}12}

注意,此处的self是用来区分构造器内的name参数和name属性的。创建类的实例时,构造器里的参数传递和函数的参数传递形式是一样的。每个属性都需要为其指定一个值,无论是在声明中(如nameOfSides),或是在构造器内(如name)。

使用 deinit 来创建一个析构器,来执行对象销毁时的清理工作。

继承和多态

子类可以加冒号后直接跟超类名,子类声明时并不需要非得制定任何标准基类,所以子类后的超类可以被忽略。

子类的方法覆盖或重载超类中的实现要加上override标记,否则,编译器会报错,编译器也会检测被标记为override的重载方法到底有没有覆盖到超类。

1classSquare: NamedShape {//接上一例,NamedShape为超类2var sideLength: Double34init(sideLength: Double, name: String) {5self.sideLength =sideLength6super.init(name: name)7numberOfSides = 48}910func area() ->Double {11returnsideLength *sideLength12}1314override func simpleDescription() ->String {//在此处用override重载了上一例中超类NameSpace的方法simpleDescription15return"A square with sides of length \(sideLength)."16}17}18let test = Square(sideLength: 5.2, name:"my test square")19test.area()20test.simpleDescription()

练习:

编写另一个NamedShape的子类:Circle ,传入半径和名字作为参数到其构造器,并在Circle类中实现area和describe方法。

此外,声明过的属性通常还有一个get和一个set方法:

1classEquilateralTriangle: NamedShape {2var sideLength: Double = 0.034init(sideLength: Double, name: String) {5self.sideLength =sideLength6super.init(name: name)7numberOfSides = 38}910var perimeter: Double {11get {12return3.0 *sideLength13}14set {15sideLength = newValue / 3.016}17}1819override func simpleDescription() ->String {20return"An equilateral triagle with sides of length \(sideLength)."21}22}23var triangle = EquilateralTriangle(sideLength: 3.1, name:"a triangle")24triangle.perimeter25triangle.perimeter = 9.926triangle.sideLength

上例中,perimeter的set中值的默认名是newValue,你可以再set后面以小括号的方式为其指定其它的名字。

请注意, EquilateralTriangle类的构造器有三个不同的步骤:

第一步,设置子类各个属性的值;

第二步,调用超类的构造器;

第三步,改变超类中定义的属性的值,其它的方法,get,set等都可以在此一步骤实行。

如果你不需要计算属性的值,但是想在设置属性值之前或之后执行代码,那么你可以使用willset(之前)和didset(之后)。如下例中的类--确保三角形的边长始终与矩形边长相等:

1classTriangleAndSquare {2var triangle: EquilateralTriangle {3willSet {4square.sideLength =newValue.sideLength5}6}7var square: Square {8willSet {9triangle.sideLength =newValue.sideLength10}11}12init(size: Double, name: String) {13square =Square(sideLength: size, name: name)14triangle =EquilateralTriangle(sideLength: size, name: name)15}16}17var triangleAndSquare = TriangleAndSquare(size: 10, name:"another test shape")18triangleAndSquare.square.sideLength19triangleAndSquare.triangle.sideLength20triangleAndSquare.square = Square(sideLength: 50, name:"larger square")21triangleAndSquare.triangle.sideLength

类的方法与函数有一个重要的区别:函数的参数名仅作用于此函数内,而方法的参数名可以用于调用方法(第一个参数除外)。缺省时,一个方法有一个同名的参数,调用时就是方法本身。你可以指定第二个名字,在方法内部使用:

1classCounter {2var count: Int =03func incrementBy(amount: Int, numberOfTimes times: Int) {4count += amount *times5}6}7var counter =Counter()8counter.incrementBy(2, numberOfTimes: 7)

当与可选值(详见第三章的If语句介绍)一起工作时,你可以在方法或属性前写 "?" 操作符。如果值在"?"之前就已经是 nil ,所有在 "?" 之后的都会自动忽略,而整个表达式是 nil 。另外,可选值是未封装的,所有 "?" 之后的都作为未封装的值。在这两种情况中,整个表达式的值是可选值:

1let optionalSquare: Square? = Square(sideLength: 2.5, name:"optional square")//?可选值的介绍详见第三章的If语句部分2let sideLength = optionalSquare?.sideLength

谢谢,Swifter-QQ群:362232993,同好者进~

github地址:https://github.com/Joejo/Swift-lesson-for-chinese

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航