美文网首页
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 类与结构体

    类与结构体的共同点: 定义属性用于存储值 定义方法用于提供功能 定义附属脚本用于访问值 定义构造器用于生成初始化值...

  • 第九章 类和结构体

    c++中,结构体是稍有不同的类,类能做的,结构体也可以; 而swift中,结构体与类有较大区别, 结构体与类的区别...

  • Swift结构体内存初探之写时复制

    Swift赋予了结构体很多余类相同的特性,以至于Swift推荐在程序中使用结构体来存储结构化数据(关于类与...

  • iOS知识点-8.类(class)和结构体(struct)有什么

    Swift Basics 类(class)和结构体(struct)有什么区别? Swift中,类是引用类型,结构体...

  • Swift学习_基本语法之枚举&类&结构体

    1.枚举 类和结构体 在swift中类和结构体类似,可以把结构体理解成是一种轻量级的类,在swift中结构体不仅可...

  • Swift第2次小结

    内容来源 Swift 5.1 教程 结构体和类 Swift 并不要求你为自定义的结构体和类的接口与实现代码分别创建...

  • Swift:类和结构体

    中文文档 一、类和结构体对比 Swift 中类和结构体有很多共同点。共同处在于: 与结构体相比,类还有如下的附加功...

  • Swift5.x-属性(中文文档)

    引言 继续学习Swift文档,从上一章节:结构体和类,我们学习了Swift结构体和类相关的内容,如结构体和类的定义...

  • Swift学习

    Swift类与结构体的区别 struct People {var name : Stringinit(name :...

  • swift4.0-11 类和结构体

    代码学习swift4.0, 类和结构体 //// main.swift// SwiftLearn11-类和结构...

网友评论

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

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