11.Swift类和结构体

2018-07-03  本文已影响0人  biyu6
/**Swift中的 类class 和 结构体struct 有很多共同点:
    定义属性用于存储值
    定义方法用于提供功能
    定义下标操作使得可以通过下标语法来访问实例所包含的值
    定义构造器,用于生成初始化值
    通过扩展以增加默认实现的功能
    实现协议以提供某种标准功能

 类 还有以下的附加功能:
    允许一个类继承另一个类的特征
    类型转换允许在运行时检查和解释一个类实例的类型
    析构器允许一个类实例释放任何其所被分配的资源
    引用计数允许对一个类的多次引用
 
 结构体 是通过被复制的方法在代码中传递,不使用引用计数
 */

//定义语法:每一次定义类或结构体时,实际上是定义了一个新的Swift类型
class SomeClass {
    //在这里定义类
}
struct SomeStructure {
    //在这里定义结构体
}
//定义示例:
struct Resolution { //定义一个分辨率的结构体,结构体中包括宽高两个存储属性
    var width = 0 //当初始化为0的时候,他会被自动推断为Int类型
    var height = 0
}
class VideoMode { //定义一个视频模式的类,包含四个变量存储属性
    var resolution = Resolution() //分辨率,属性类型被推断为上面定义的Resolution结构体
    var interlaced = false //
    var frameRate = 0.0 //帧率
    var name: String? // 可选类型,默认值为nil
}
//生成类实例 和 结构体实例  通过下面方式创建的类或者结构体实例,其属性均会被初始化为默认值
var someResolution = Resolution()
let someVideoMode = VideoMode()
print("分辨率的宽为:\(someResolution.width) 视频模式的分辨率宽为:\(someVideoMode.resolution.width)")
someResolution.width = 1280
someVideoMode.resolution.width = 860 //Swift允许设置结构体属性(resolution)的子属性(width),
print("分辨率的宽为:\(someVideoMode.resolution.width) ==== \(someResolution.width)")

//结构体有一个自动生成成员的逐一构造器,用于初始化新结构体实例中成员的属性。
let vga = Resolution(width: 480, height: 640)

//============================结构体和枚举 是 值类型============================
//值类型:枚举和结构体都是值类型,所有的基本类型Int、Float、Bool、String、Array、Dictionary都是值类型,底层是以结构体的形式所实现。值类型被赋予给一个变量、常量或者被传递给一个函数的时候,其值会被拷贝
//结构体类型是值类型的验证示例:
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd // 拷贝了一份值
cinema.width = 860 //修改了值
print("hd的宽度:\(hd.width) , cinema的宽度:\(cinema.width)")//1920--860

//枚举是值类型的验证示例:
enum CompassPoint {
    case North,South,East,West
}
var currentDirection = CompassPoint.West // 现在的方向是 西方
let rememberedDirection = currentDirection // 将 西方 赋值给记忆中的方向
currentDirection = .East // 现在的方向变成了 东方
if rememberedDirection == .West {
    print("记忆中的方向仍然没有改变,还是西方")
}

//============================类 是 引用类型============================
//引用类型: 引用类型在被赋予到一个变量、常量或者被传递到一个函数时,引用的是已经存在的实例本身,而不是其值的拷贝。
let tenEighty = VideoMode()//定义一个 八十年代的 视频模式的类的 实例
tenEighty.resolution = hd // 分辨率是 1920,1080
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0

let alsoTenEighty = tenEighty // 一个新的实例
alsoTenEighty.frameRate = 30.0

print("八十年代的帧率是:\(tenEighty.frameRate)") // 帧率被改变为30.0,因为他们实际上引用的是相同的videoMode实例
//注意: tenEighty 和 alsoTenEighty 被声明为常量,但依然可以改变frameRate属性的值;因为这连个实例仅仅是对VideoMode实例的引用,而不是存储VideoMode实例,所以改变的是被引用的VideoMode的frameRate属性。

//============================恒等运算符============================
//因为类是引用类型,有可能有多个常量或者变量同时引用了同一个类的实例,为了判断两个常量或变量 是否同时 引用了 一个类实例;Swift退出了恒等运算符: 等价于===、不等价于 !==
if tenEighty === alsoTenEighty { // 是否引用了同一个类实例
    print("这两个常量 引用了 同一个 VideoMode类的实例")
}

//============================数据类型:结构体 和 类 的选择============================
/** 绝大多数自定义数据类型构造都应该是类,而非结构体。但如果符合下面的一条或多条,建议用结构体:
    1.该数据结构的主要目的是 用来封装少量相关简单数据值
    2.预计该数据结构的实例在被赋值或传递是,封装的数据将 会被拷贝而不是被引用
    3.该数据结构中储存的值类型属性,也应该被拷贝,而不是被引用
    4.该数据结构中 不需要去继承另一个既有类型的属性或行为
 举例来说,以下情景中适合使用结构体:
    几何形状的大小,封装一个width属性和height属性,两者均为Double类型
    一定范围内的路径,封装一个start属性和length属性,两者均为Int类型
    三维坐标系内一点,封装x,y,z属性,三者均为Double类型
 */

上一篇 下一篇

猜你喜欢

热点阅读