Swift学习笔记三-对象和类

Swift有很多高级特性,个人感觉Swift在语法跟数据结构上比Java要高级好多.

声明类
import Foundation  
//使用class和类名创建一个类.类中属性的声明和常量,变量声明一样,唯一的区别就是它们的上下文是类.同样,方法同函数声明也一样.
class Shape {  
    var numberOfSides = 0
    let maxNumber = 0
    func simpleDescripe() -> String {
        return "A shape with \(numberOfSides) sides"
    }
    func calMaxNumber(number:Int) -> String {
        return "The max number is \(number)"
    }
}
实例化类并访问属性调用方法
//要创建一个类的实例,在类名后面加上括号,用点语法访问属性和方法
var shape = Shape()  
shape.numberOfSides = 7  
var shapeDescription = shape.simpleDescripe()  
创建构造器(构造方法)
//上面的类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是用来区别实例变量的.当创建实例的时候,像给函数传入参数一样一样给类的构造函数传入函数,每个属性都需要被赋值,不然会报错--无论是通过声明(像numberOfSides)还是通过构造函数(就像name)
//如果需要在删除对象之前进行清理操作,使用deinit创建一个析构函数
继承父类重写方法
//子类的定义方法是在他们的类名后面加上父类的名字,用冒号分隔.创建类的时候并不需要一个标准的根类,所以可以忽略父类.
//子类如果要重写父类的方法,需要用override标记.如果没用标记就重写父类方法编译器会报错.编译器同样会检测override标记的方法是否确实在父类中.
class Sequare: 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 is \(sideLength)"
    }
}
let sequare = Sequare(sideLength: 5.0, name: "xiaoming")  
sequare.area()  
sequare.simpleDescription()

//练习: 创建NamedShape的另一个子类Circle,构造器接收两个参数,一个是半径一个是名称,在子类Circle中实现area()和simpleDescription()方法。
class Circle:NamedShape {  
    var radius:Double
    init(radius: Double, name: String) {
        self.radius = radius
        super.init(name: name)
    }

    func area() -> Double {
        return radius * radius * 3.14
    }

    override func simpleDescription() -> String {
        return "A circle with radius of length is \(radius)"
    }
}
属性的setter和getter
//除了存储简单的属性之外,属性还可以有getter方法和setter方法
//在swift中使用get/set 主要是用来间接获取/改变其他属性的值。在swift中这类属性被称之为“计算属性” ,不要拿其他面向对象语言跟Swift作对比(尤其是Java,OC,Java中的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
        }
//        set(value) {
//            sideLength = value / 3.0
//        }
    }
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")  
print(triangle.perimeter)  
triangle.perimeter = 9.9  
print(triangle.sideLength)  
//在perimeter的setter中,新值的名字是newValue.可以在set之后显式设置一个名字.
//注意:EquilateralTriangle类的构造器执行了三步:
//1.设置子类声明的属性值
//2.调用子类构造器
//3.改变父类定义的属性值.其他的工作比如调用方法,getters和setters也可以在这个阶段完成.
属性监视willSet跟didSet
//如果不需要计算属性,但是仍然需要在设置一个新值之前或者之后运行代码,使用willSet或者didSet.willSet跟didSet用来监视除初始化之外的属性值的变化.当这个值变化之前做点什么别的事,变化之后做点什么别的事.
//比如,下面的了确保三角形的变成总是和正方形的变成相同
class TriangleAndSquare {

    var  triangle: EquilateralTriangle {
        willSet {
            sequare.sideLength = newValue.sideLength
        }
//        willSet(value) {
//            print("willSet")
//            sequare.sideLength = value.sideLength
//        }
    }

    var sequare: Sequare {
        willSet {
            triangle.sideLength = newValue.sideLength
        }
    }

    init(size: Double, name: String) {
        sequare = Sequare(sideLength: size, name: name)
        triangle = EquilateralTriangle(sideLength: size, name: name)
    }
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "Another test sequare")  
print(triangleAndSquare.sequare.sideLength)  
print(triangleAndSquare.triangle.sideLength)  
triangleAndSquare.sequare = Sequare(sideLength: 50, name: "larger sequare")//只有这句才能调用willSet,初始化不调用  
print(triangleAndSquare.triangle.sideLength)  
处理可选值
//处理变量的可选值时,可以在操作(比如属性,方法,子脚本)之前加?.如果?之前的值是nil,则?后面的内容会被忽略,并且整个表达式返回nil.否则?之后的内容都会被执行.这两种情况下整个表达式也是一个可选值
let optionalSquare: Sequare? = Sequare(sideLength: 20, name: "optional")  
let sideLength = optionalSquare?.sideLength  
print(sideLength!)  

--EOF--