类和结构体对比

Swift 中类和结构体有很多共同点。共同处在于:

  • 定义属性用于储存值
  • 定义方法用于提供功能
  • 定义下标用于通过下标语法访问值
  • 定义初始化器用于生成初始化值
  • 通过扩展以增加默认实现的功能
  • 符合协议以对某类提供标准功能

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

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

1.定义

//定义类class
class 角色 {
    //class成员必须赋值
    var id = ""
    var money = 0
    //class类可以改变属性值
    func 安全区角色(id: String, money: Int) {
        self.id = id
        self.money = money
        print("当前角色是\(self.id),money有\(self.money)")
    }
}

var 小黄 = 角色()
小黄.安全区角色(id: "小黄", money: 999)//当前角色是小黄,money有999

//定义结构体struct
struct 坐标 {
    //struct成员可以不赋值,但必须声明类型
    var x = 0, y = 0
    //结构体/枚举实例默认不可改变属性值. 若需要修改,须加上mutating关键字.
    mutating func 安全区坐标1(x: Int, y: Int) {
        self.x = x
        self.y = y
        print("当前已回到安全区,坐标是\(self.x),\(self.y)")
    }
}

var 小黄的坐标 = 坐标()
小黄的坐标.安全区坐标1(x: 1, y: 2)//当前已回到安全区,坐标是1,2

2.实例属性

2.1 struct与struct的实例传递

在实例传递时,类是被引用的,结构体和枚举类型则是被复制的。

//重点:在实例传递时,类是被引用的,结构体和枚举类型则是被复制的

//1.创建类的实例
let xiaohong = 角色()   //id:"",money:0
xiaohong.money //0

//2.实例传递
let xiaoming = xiaohong
//3.使用class
xiaoming.id = "小明"    //id:"小明",money:0
xiaoming.money = 5000 //id:"小明",money:5000
//4.改变xiaoming实例后xiaohong的值
xiaohong.money //5000,说明类是被引用的

//1.创建结构体的实例,所有结构体会默认生成一个逐个设置属性的构造方法 而类不会
var 小红坐标 = 坐标() //x:0,y:0
小红坐标 = 坐标(x:100,y:200)   //x:100,y:200
小红坐标.x  //100

//2.实例传递
var 小明坐标 = 小红坐标
//3.使用struct,与类不同,必须实例是变量类型才能改变值
小明坐标.x = 10    //x:10,y:0
小明坐标.y = 20 //x:10,y:20
//4.改变小明坐标实例后小红坐标的值
小红坐标.x  //100,说明结构体是被复制的

2.2 class,struct,enum的综合使用

例:

enum 移动方式 {
    case 走
    case 跑
    case 骑
    case 传送
}

class 法师: 角色 {
    var 人物坐标 = 坐标()
    var 人物移动方式 = 移动方式.走

    //由人物坐标与人物移动方式计算得出,人物坐标与人物移动方式改变后需手动更新当前坐标,法师的人物坐标与人物移动方式才会更新
    var 当前坐标: 坐标 {
        get {
            switch 人物移动方式 {
            case .走:
                人物坐标.x += 1
                人物坐标.y += 1
            case .跑:
                人物坐标.x += 3
                人物坐标.y += 3
            case .骑:
                人物坐标.x += 10
                人物坐标.y += 10
            case .传送:
                人物坐标.x += 1000
                人物坐标.y += 1000
            }  
            return 人物坐标
        }

        set {
            人物坐标 = newValue
        }
    }
}

var 法师1 = 法师()  //id:"",money:0;x:0,y:0;走
//更新前的法师1属性
法师1 //id:"",money:0;x:0,y:0;走
//更新当前坐标,更新 初始移动方式:走 的当前坐标
法师1.当前坐标    //x:1,y:1
//更新后的法师1属性
法师1 //id:"",money:0;x:1,y:1;走

法师1.人物移动方式 = .跑
法师1.当前坐标    //x:4,y:4

法师1.人物移动方式 = .传送
法师1.当前坐标    //x:1004,y:1004

法师1 //id:"",money:0;x:1004,y:1004;传送
//计算属性的setter方法,影响其他属性
法师1.当前坐标 = 坐标(x: 2000, y: 90)
法师1 //id:"",money:0;x:2000,y:90;传送
法师1.人物坐标    //x:2000,y:90

2.3 属性监视器: 对属性值的变化进行响应.

willSet: 事前响应. 新值 newValue
didSet : 事后响应. 旧值 oldValue

/*
 swift中基础数学函数:
 - sqrt(n)用来计算n的平方根
 - pow(x, n)用来计算x的n次方
 - abs(x)用来计算x的绝对值 
 */
class 移动距离 {
    var 当前坐标 = 法师1.人物坐标 {
        willSet {
            print("当前坐标是:\(newValue)!")
        }
        didSet {
            //注意:sqrt在playground中不可用,swift中可以
//            let 最新移动距离 = sqrt(pow(当前坐标.x - oldValue.x,2) + pow(当前坐标.y - oldValue.y,2))

            print("x轴移动了\(当前坐标.x - oldValue.x)米移动距离!")
            print("y轴移动了\(当前坐标.y - oldValue.y)米移动距离!")
        }
    }
}

var 移动距离1 = 移动距离()  //当前坐标 {x 2000,y 90}
移动距离1.当前坐标 = 坐标(x:100,y:200)
移动距离1.当前坐标 = 坐标(x:200,y:250)
/*
 当前坐标是:坐标(x: 100, y: 200)!
 x轴移动了-1900米移动距离!
 y轴移动了110米移动距离!
 当前坐标是:坐标(x: 200, y: 250)!
 x轴移动了100米移动距离!
 y轴移动了50米移动距离!
 */

3. 类型属性

类型属性:属于类型固有的,实例不能调用.
重写父类的属性:重写父类的属性或者方法要使用关键字 override 进行修饰

class 生命体 {
    var width = 0
    class var 遗传方式 :String {
        return "RNA"
    } 
}

生命体.遗传方式    //"RNA"

class Human: 生命体 {
    //重写父类的属性  重写父类的属性或者方法要使用关键字 override 进行修饰
    override class var 遗传方式 :String {
        return "DNA"
    }
}

Human.遗传方式  //"DNA"
生命体.遗传方式    //"RNA"

let i = Human() //Human
i.width //0

struct 逛街 {
    static let 试衣间 = "UNIClO"
    static let 网站 = "http://www.taobao.com?cate="
    var cate = ""

    var shareUrl : String {
        return 逛街.网站 + cate
    }
}

逛街.试衣间  //"UNIClO"

let 逛淘宝 = 逛街(cate: "seafood")

逛淘宝.shareUrl    //"http://www.taobao.com?cate=seafood"