Swift类

作者: Mi欧阳 | 来源:发表于2016-03-18 09:45 被阅读140次

Swift中类以关键字class开头

1.最基本例子

class Shape {  //类名
    var numberOfSides = 0  //类属性(全局变量)
    func simpleDescription() -> String {  //类方法
        return "A shape with \(numberOfSides) sides." }
}

2.重写init方法

class NamedShape {
    var numberOfSides: Int = 0
    var name: String
    init(name: String) { //重写默认的init方法
        //name在init时就赋值,这样设置的属性一般不会在后续代码中修改其值
        self.name = name
    }
    func simpleDescription() -> String {
        return "A shape name :\(name) with \(numberOfSides) sides."
    }
    
    deinit{  //重写默认的销毁方法(相当于delloc)
        
    }
}

var nameShape = NamedShape(name: "Test Shape")
nameShape.numberOfSides = 5
nameShape.simpleDescription()

3.继承

/*
重写init方法,注意Swift和OC不同。Swift的super.init是确保所有子类的属性都初始化完成后书写的,不像OC基本都是写在最前面。原因是,编辑器在执行子类init的init时会优先判断子类自己能不能被成功创建。如果不行,也就没必要去init父类,这样更加节省资源。
所以在Swift中子类的初始化顺序是:
1.设置子类声明属性的值
2.调用父类的初始化器
3.更改父类中定义的属性值。任何额外的设置工作,如使用方法、getter 或 setter 也可以在这里完成(可选操作)
*/
class Square: NamedShape {
    var sideLength: Double
    //重写init方法
    init(sideLength: Double , name: String) {
        self.sideLength = sideLength  //先实例化子类变量
        super.init(name: name)  //父类init
        numberOfSides = 4  //父类属性值更改
    }
    
    func area() -> Double {  //子类方法
        return sideLength * sideLength
    }
    //override 关键字  代表重写
    override func simpleDescription() -> String {
        return "A square with name: \(name) , numberOfSides:\(numberOfSides) , sides of length \(sideLength)."
    }
}

var test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()

4.属性关联,get 和 set 的用法
get/set被称为"计算属性",它们不直接存储值,但是可用来操作其他属性值的变化

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 {  //重写perimeter的get方法
            return 3.0 * sideLength
        }
        set { //重写perimeter的set方法
            sideLength = newValue / 3.0
        }
    }
    override func simpleDescription() -> String {
        return "An equilateral triagle with sides of length \(sideLength) , perimeter is \(perimeter) ."
    }
}

5.属性监视器(willSet/didSet)
如果方法本身不需要计算某个属性,但方法中的属性仍然需要提供在运行之前和设置新值后的代码,可以使用 willSet 和 didSet (属性监视器)。

//TriangleAndSquare类要确保其三角的边长和正方形的边长一样。
class TriangleAndSquare {
    var triangle: EquilateralTriangle {
        //这个类本身不需要对sideLength进行计算,但它里面的属性需要根据sideLength变化而变化
        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)
    }
}

let triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength   //输出10
triangleAndSquare.triangle.sideLength  //输出10
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLength  //输出50

6.函数、方法、实例方法、类方法
在其他语言中,可能函数和方法是分开来的,相互不包括的,但是在Swift中。方法就是函数的一种。一切使用"func"关键字的为都是函数,在外面的是函数,在类中的就是称他为方法,方法中又分"实例方法"和"类方法"

class Counter {
    var count: Int = 0
    //对于incrementBy1来说numberOfTimes是外部参数名,times是内部参数名
    func incrementBy1(amount: Int, numberOfTimes times: Int) {
        count = amount * times
    }
    //"_"关键字代表可以外部调用时可以省略参数名
    func incrementBy2(amount: Int,_ times: Int) {
        count = amount * times
    }
    //类方法加上关键字class,类方法不能使用类中的属性
    
}

func incrementBy4(var a1: Int,a2: Int) {
    a1 = a1 + a2
}

var counter = Counter()
counter.incrementBy1(2, numberOfTimes: 7) //实例方法
counter.incrementBy2(2,7)  //实例方法
incrementBy4(1, a2: 2)  //函数

7.类属性和类方法

class TestCount {
    var testInt:Int = 10 //实例属性
    //类属性 类属性中只允许使用计算属性(get\set)
    class var baseInt:Int{
        return 10  //这个是简写的get,这个属性是只读属性
    }
    class func incrementBy3(times: Int) ->Int {
        return baseInt * times
        //return testInt * times  //类方法不能调用实例属性
    }
}

TestCount.baseInt  //调用类属性,类不需要实例化
TestCount.incrementBy3(2) //调用类方法,类不需要实例化

8.下标, 或者叫附属脚本(subscript)。
可以定义在 类/结构体/枚举中,进行快速访问。

/*
//格式:也可以设定set/get(和类方法很相似)
subscript(index:Int) -> Int{
    get{

    }
    set{

    }
}
*/
struct Person12{   //定义一个结构体
    let baseLength:Int
    //结构体在这里可以不写初始化方法,会自动生成
    subscript(index:Int) -> Int{ //下标方法,无方法名
        return baseLength * index
    }
}

var p12 = Person12(baseLength: 10)
p12[3]     //直接像访问数组一样访问.

9.可选值
当与可选值一起工作时,你可以在操作前写“?”,类似于方法、属性和下标。如果在“?”之前该值已经是 nil,所有“?”之后的东西都会自动忽略,整个表达式的值就是 nil。否则,可选值是未包装的,所有“?” 之后的均视为未包装值。在这两种情况下,整个表达式的值是一个可选值。

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength

10.lazy关键字
使用lazy(延迟)关键字存储属性: 当使用该属性时才进行初始化, 好处是避免空间浪费

class Person1{
    var name = "jack"
    //    class var height:Int = 10   //错误! 类中不能有全局存储属性的, 只能是计算属性. 见下文说明
}

class Person3{
    var name:String = "xuneng"  //需要手动初始化
    var age:Int = 10
    let height = 175
    lazy var p1:Person1 = Person1() //延迟关键字, 必须是var
}

var p3 = Person3()
p3.name   //通过点语法来访问
p3.age = 11   //设置
print(p3.p1)   //这句调用时, p1才进行初始化

相关文章

网友评论

    本文标题:Swift类

    本文链接:https://www.haomeiwen.com/subject/azgclttx.html