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


      

      Class 类

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

    1 class Shape {
    2     var numberOfSides = 0
    3     func simpleDescription() -> String {
    4         return "A shape with (numberOfSides) sides."
    5     }
    6 }

    练习:

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

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

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

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

     1 class NamedShape {
     2     var numberOfSides: Int = 0
     3     var name: String
     4     
     5     init(name: String) {
     6         self.name = name
     7     }
     8     
     9     func simpleDescription() -> String {
    10         return "A shape with (numberOfSides) sides."
    11     }
    12 }

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

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

      继承和多态

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

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

     1 class Square: NamedShape {//接上一例,NamedShape为超类
     2     var sideLength: Double
     3     
     4     init(sideLength: Double, name: String) {
     5         self.sideLength = sideLength
     6         super.init(name: name)
     7         numberOfSides = 4
     8     }
     9     
    10     func area() ->  Double {
    11         return sideLength * sideLength
    12     }
    13     
    14     override func simpleDescription() -> String {//在此处用override重载了上一例中超类NameSpace的方法simpleDescription
    15         return "A square with sides of length (sideLength)."
    16     }
    17 }
    18 let test = Square(sideLength: 5.2, name: "my test square")
    19 test.area()
    20 test.simpleDescription()

    练习:

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

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

     1 class EquilateralTriangle: NamedShape {
     2     var sideLength: Double = 0.0
     3     
     4     init(sideLength: Double, name: String) {
     5         self.sideLength = sideLength
     6         super.init(name: name)
     7         numberOfSides = 3
     8     }
     9     
    10     var perimeter: Double {
    11     get {
    12         return 3.0 * sideLength
    13     }
    14     set {
    15         sideLength = newValue / 3.0
    16     }
    17     }
    18     
    19     override func simpleDescription() -> String {
    20         return "An equilateral triagle with sides of length (sideLength)."
    21     }
    22 }
    23 var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
    24 triangle.perimeter
    25 triangle.perimeter = 9.9
    26 triangle.sideLength

      

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

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

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

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

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

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

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

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

    1 class Counter {
    2     var count: Int = 0
    3     func incrementBy(amount: Int, numberOfTimes times: Int) {
    4         count += amount * times
    5     }
    6 }
    7 var counter = Counter()
    8 counter.incrementBy(2, numberOfTimes: 7)

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

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

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

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

      

  • 相关阅读:
    Django开发笔记一
    Netty+SpringBoot写一个基于Http协议的文件服务器
    SQL优化
    mysql 字符串数字转换
    git 常用的命令总结
    eclipse 使用Maven deploy命令部署构建到Nexus
    intellij idea远程debug调试resin4教程
    postman 请求种添加用户权限
    对List中每个对象元素按时间顺序排序
    List根据时间字符串排序
  • 原文地址:https://www.cnblogs.com/joejs/p/3766565.html
Copyright © 2020-2023  润新知