Swift学习3---类和对象

1.创建和使用类

  使用 class 和类名来创建一个类。类中属性的声明和常量、变量声明一样,唯一的区别就是 它们的上下文是类。同样,方法和函数声明也一样。 

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

  创建Shape类的实例,并调用其字段和方法。

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

注意:通过init构建对象,既可以使用self显式引用成员字段(name),也可以隐式引用(numberOfSides)。

   如果你需要在删除对象之前进行一些清理工作,使用 deinit 创建一个析构函数进行清理。 

2.继承和多态

  子类的定义方法是在它们的类名后面加上父类的名字,用冒号分割。创建类的时候并不需要 一个标准的根类,所以你可以忽略父类。 

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()

  为了简化代码,Swift引入了属性(property),见下面的perimeter字段:

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

注意:赋值器(setter)中,接收的值被自动命名为newValue你可以在 set 之后显示的设置一个名 字。 

3.willSet和didSet

  注意 EquilateralTriangle 类的构造器执行了三步:
  1. 设置子类声明的属性值
  2. 调用父类的构造器
  3. 改变父类定义的属性值。其他的工作比如调用方法、getters 和 setters 也可以在这个阶 段完成。

  如果你不需要计算属性但是需要在设置一个新值之前运行一些代码,使用 willSet 和 didSet。 

class TriangleAndSquare {
    var triangle: EquilateralTriangle {
    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 = EquilateralTriangle(sideLength: size, name: name)
    }
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLengt

比如,上面的类确保三角形的边长总是和正方形的边长相同 

4.调用方法

  Swift中,函数的参数名称只能在函数内部使用,但方法的参数名称除了在内部使用外还可以在外部使用(第一个参数除外),例如:

class Counter {
    var count: Int = 0
    func incrementBy(amount: Int, numberOfTimes times: Int) {
        count += amount * times
    }
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)
//注意Swift支持为方法参数取别名:在上面的代码里,numberOfTimes面向外部,times面向内部。

5.?的另一种用途

  使用可空值时,?可以出现在方法、属性或下标前面。如果?前的值为nil,那么?后面的表达式会被忽略,而原表达式直接返回nil,例如:

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional 
square")
let sideLength = optionalSquare?.sideLength
//optionalSquarenil时,sideLength属性调用会被忽略。

6.补充

初始化

  init关键词,和OC一样。不过这块非常像CPP,如下面这东西

class nyan{ 
        var num: Int = 1024 
        init() 
        { 
            num = 1; 
        } 
    } 
      
    class miao:nyan 
    { 
        var num1: Int = 1

      override init() { 

            num1 = 2 
        } 
    } 

var a = miao() 
      
println(a.num) 
println(a.num1) 
//
如果以OC的思维来看,它输出的应该是 1024, 2。因为OC只要没有call super,就是覆盖掉了。
//但实际上Swift输出的是 1, 2。倘若,我们在两个init加上打log的话,会发现,子类的init先运行,然后运行父类的。那么什么时候在子类的init里面call super.init()呢?
显而易见:当在子类里面要调用父类的成员变量时,要先调用super.init()去初始化它,若没有写的话,XCode会报编译错误。

 

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。