美文网首页
Learn Swift - Section 3rd 类与结构体

Learn Swift - Section 3rd 类与结构体

作者: starfox寒流 | 来源:发表于2016-05-11 10:34 被阅读30次

    类与结构体的共同点:

    • 定义属性用于存储值
    • 定义方法用于提供功能
    • 定义附属脚本用于访问值
    • 定义构造器用于生成初始化值
    • 通过扩展以增加默认实现的功能
    • 实现协议以提供某种标准功能

    与结构体相比,类还有如下的附加功能:

    • 继承允许一个类继承另一个类的特征
    • 类型转换允许在运行时检查和解释一个类实例的类型
    • 解构器允许一个类实例释放任何其所被分配的资源
    • 引用计数允许对一个类的多次引用

    更多信息请参见继承,类型转换,析构过程,和自动引用计数。

    注意

    • 结构体总是通过被复制的方式在代码中传递,不使用引用计数。

    <h3 id = "1">1.值类型与引用类型</h3>
    值类型被赋予给一个变量、常量或者被传递给一个函数的时候,其值会被拷贝。

    在之前的章节中,我们已经大量使用了值类型。实际上,在 Swift 中,所有的基本类型:整数(Integer)、浮点数(floating-point)、布尔值(Boolean)、字符串(string)、数组(array)和字典(dictionary),都是值类型,并且在底层都是以结构体的形式所实现。

    在 Swift 中,所有的结构体和枚举类型都是值类型。这意味着它们的实例,以及实例中所包含的任何值类型属性,在代码中传递的时候都会被复制。

    “与值类型不同,引用类型在被赋予到一个变量、常量或者被传递到一个函数时,其值不会被拷贝。因此,引用的是已存在的实例本身而不是其拷贝。”

    var marray = ["lopl","liu","han"]
    func modifyArray()  {
        var saray = marray
        saray.removeAtIndex(2)
    }
    modifyArray()
    marray//并没有变,说明是值拷贝
    

    <h3 id = "2">2.将结构体实例赋值给一个常量,则无法修改结构体中的属性,即使属性是变量。</h3>

    struct Cars {
        var name = ""
    
    }
    let car = Cars()
    car.name = "Audi"
    //而类则可以修改,因为类是引用类型。
    class CreateNewLife{
        var name = ""
    }
    class Animals {
        var kind = ""
        let planet = "Earth"
        lazy var createNewLife = CreateNewLife()
    }
    let life = CreateNewLife()
    let anAnimal = Animals()
    anAnimal.kind = "Human"
    print(anAnimal,life)
    if life === anAnimal {
        print("same class")
    }else{
        print("Different class")
    }
    print(anAnimal.createNewLife.name)//这时CreateNewLife实例才会被创建
    anAnimal.createNewLife.name = "liven"
    print(anAnimal.kind,anAnimal.createNewLife.name)
    

    <h3 id = "3">3.结构体和类中的属性定义-getter和setter</h3>

    struct Point{
        var x = 0.0,y = 0.0
    }
    struct Size {
        var width = 0.0,height = 0.0
    }
    struct Rect {
        var origin = Point()
        var size   = Size()
        var center:Point{//计算属性:即写了get或set的属性。如果只有get,就是只读属性
            get{
                let centerX = origin.x + size.width/2
                let centerY = origin.y + size.height/2
                return Point(x: centerX, y: centerY)
            }
            set(newCenter){
                origin.x = newCenter.x - size.width/2
                origin.y = newCenter.y - size.height/2
            }
        }
        var arcPoint:Point{//属性观察器didSet,willSet
            willSet(newValue){//会将新的值传入
                print("will set arcPoint \(newValue)")
            }
            didSet(oldValue){//会将旧的值传入
                //arcPoint = Point(x: 8, y: 9)
                print("did set arcPoint \(arcPoint) \(oldValue)")
            }
        }
        static var name = "my rect"//Type property类型属性
    
        //值类型属性一般不能在它自己的实例方法中修改;如果非要修改,需要加关键字mutating
        mutating func bigger(x:Double,y:Double) {
            size.width  += x
            size.height += y
        }
    }
    
    Rect.name
    Rect.name = "xxxx"
    Rect.name
    
    var rect = Rect(origin: Point(x: 10,y: 10), size: Size(width: 20,height: 30), arcPoint: Point(x: 1, y: 1))
    print(rect.arcPoint)
    rect.arcPoint = Point(x: 3, y: 4)
    print(rect.arcPoint)
    
    var rect2 = rect
    rect2.arcPoint = Point(x: 6, y: 6)
    print(rect.arcPoint,rect2.arcPoint)
    
    rect.bigger(20, y: 20)
    print(rect.size)
    class SomeClass {
        class var overrideProperty:Int{//get省略了。class关键字表示重写父类的getter实现
            return 10
        }
    }
    

    <h3 id = "4">4.方法</h3>

    struct LevelTraker {
        static var highestUnlockedLevel = 1
        static func unlockLevel(level:Int){
            if (level == highestUnlockedLevel + 1) {highestUnlockedLevel = level}
        }
        static func levelIsUnlocked(level:Int)->Bool{
            return level <= highestUnlockedLevel
        }
        var currentLevel = 1
        mutating func advanceLevel(level:Int)->Bool{
            if LevelTraker.levelIsUnlocked(level) {
                currentLevel = level
                return true
            }else{
                return false
            }
        }
    }
    
    class Player {
        var traker = LevelTraker()
        var playerName:String
        func completeLevel(level:Int) ->Bool{
            LevelTraker.unlockLevel(level+1)
            if traker.advanceLevel(level+1){
    
                return true
            }else{
                print("Level \(level) hasn't been unlocked")
                return false
            }
        }
        init(name:String){
            playerName = name
        }
    }
    var level111 = LevelTraker()
    var level121 = LevelTraker()
    level121.currentLevel = 2
    print(level111.currentLevel, level121.currentLevel)
    
    var player = Player(name:"han")
    player.traker.currentLevel
    player.completeLevel(1)
    player.traker.currentLevel
    LevelTraker.highestUnlockedLevel
    player.completeLevel(5)
    

    <h3 id = "5">5.构造过程</h3>

    class Cars{
        var brand:String
        var usage:String
        //构造函数
        init(){
            brand = "BMW"
            usage = "Family"
        }
        init(_brand:String,_usage:String){
            brand = _brand
            usage = _usage
        }
    }
    
    let audi = Cars(_brand: "Audi", _usage: "Sports")
    print(audi.brand,audi.usage)
    let car2 = Cars()
    print(car2.brand,car2.usage)
    

    <h3 id = "6">6.当属性有默认值,且没有构造方法时,结构体和类拥有默认构造方法。但是结构体可以有带属性参数的默认构造方法(逐一成员构造器),而类没有。</h3>

    struct People {
        var name:String?
        var sex:String?
    }
    class Books {
        var type:String?
        var category:String?
        var available = true
    }
    let p = People()
    let semdsd = People(name: "han", sex: "famale")
    let book   = Books()
    //var book2  = Books(type:"epub",category:"Computer",available:true)
    

    <h3 id = "7">7.析构过程</h3>
    /**

    • 析构器只适用于类类型,不能用于结构体。析构器用deinit关键字。
      */
    class Telephones {
        var type:String?
        var category:String?
        var available = true
    
        init() {
            //
        }
        deinit{
            //析构代码。。。
            print("\(type)")
            available = false
        }
    }
    

    /*
    析构过程会在ARC回收实例时被系统调用,不需要手动调用。
    */

    <h3 id = "8">8.类实例之间的循环强引用</h3>
    解决方式:
    1.使用weak关键字,弱引用
    2.使用unowned,无主引用

    <h3 id = "9">9.解决闭包引起的循环引用--定义捕获列表</h3>

    protocol SellProducts{
        func sellProducts(product:String)
    }
    
    class Person {
        var name:String
        weak var delegate:Seller?
        lazy var someClosure:(Int,String)->String = {
            //在闭包中将self修饰为无主引用。将delegate 修饰为 弱引用
            [unowned self,weak delegate = self.delegate!]//捕获列表
            (index:Int,strToProcess:String)->String in
    
            return "\(self.name),\(self.delegate),\(delegate)"
        }
        init(name:String,delegate:Seller?){
            self.name = name;
            self.delegate = delegate;
        }
    
        func giveSellerProducts(product:String ) -> Bool {
    
            self.delegate?.sellProducts(product)
            return true
        }
    }
    
    class Seller : SellProducts{
        var product:String?
        func sellProducts( product: String) {
            self.product = product
        }
    }
    let seller = Seller()
    var person = Person (name: "Hanliu", delegate: seller)
    
    
    //刚开始seller是没有商品的,要等到Person给seller
    print(seller.product)
    //person告诉seller,帮我卖苹果
    person.giveSellerProducts("apple")
    //现在seller手中就有了商品了
    print(seller.product!)
    
    person.someClosure(1,"haha")
    

    相关文章

      网友评论

          本文标题:Learn Swift - Section 3rd 类与结构体

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