首页 > 代码库 > Welcome to Swift (苹果官方Swift文档初译与注解四)---19~28页

Welcome to Swift (苹果官方Swift文档初译与注解四)---19~28页

在Swift中,函数实际上是一种特殊的组合体(闭包),你也可以定义匿名的组合体(闭包),将代码写在({})中,并使用in 来分隔参数和返回值.

  numbers.map({

      (number: Int) -> Int in

      let result = 3 * number

      return result

      })

  EXPERIMENT // 练习题

  Rewrite the closure to return zero for all odd numbers. // 重写编写一个组合体,返回值为0;

为了更精确的使用组合体(闭包),你可以有几种选择.当类型是明确的时候,比如代理的回调函数,你可以忽略它的参数的类型,以及返回值类型.单语句的组合体,隐式的返回它执行语句的值.

  numbers.map({ number in 3 * number })

参数的指定使用数字取代名称,这个方法对于非常简短的组合体(闭包)特别适用. 一个组合体(闭包)作为函数的最后参数传递值的时候,可以紧跟在()后面.

  sort([1, 5, 3, 12, 2]) { $0 > $1 }

Objects and Classes

/*对象和类*/

在Swift中,使用class关键字再加上类名来创建一个类.类中的成员/属性声明方法与之前的常量/变量声明一样,只是它们必须在类的定义内.同样,方法和函数也是如此.

  class Shape {

      var numberOfSides = 0

      func simpleDescription() -> String {

          return "A shape with \(numberOfSides) sides."

      }

  }

  EXPERIMENT // 练习题

  Add a constant property with let, and add another method that takes an argument. //使用let添加一个常量属性,再添加一个带有参数的方法;

创建类的实例是在类名的后面加一个(),访问实例方法和实例成员使用点语法.

  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."

      }

  }

注意上述代码中,self是怎样在初始化中区分name属性与name参数的.创建一个类的实例时,参数name的传递就像函数调用时一样.每个属性成员都需要分配一个值无论是在声明中还是在初始化里.

使用 deinit 定义一个注销对象的方法,在这个方法里你可以在对象被销毁前执行一些清理事情.

子类的写法是在类名后面使用:再加上父类的名称.在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()

  EXPERIMENT // 练习题

  Make another subclass of NamedShape called Circle that takes a radius and a name as arguments to its initializer. Implement an area and a describe method on the Circle class.

             /**设计一个继承NamedShape类的子类Circle,并初始化它的成员变量radius和name,再给类添加area和describe方法*/

类的另一种简便存取成员变量的方式是,使用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

      }

      }

    

      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

在上述代码例子中,成员变量perimeter的setter方法有一个隐含的变量 newValue,也可以在set后添加(),在其中明显的定义这个变量.

注意在 EquilateralTriangle类中 初始化有三个不同的步骤:

  1. 设置子类声明的成员变量的值;
  2. 调用父类的初始化;
  3. 修改父类定义的成员变量值,以及其他的一些使用getter或者setter再或者实例方法来完成的工作.

/*************后续内容,敬请期待***********/