Swift-类和结构体(Class and Structures)(八)
来源:互联网 发布:matlab软件有多大 编辑:程序博客网 时间:2024/06/15 07:05
前言
与其他编程语言不通,Swift并不要求我们为自定义的类和结构体去创建独立的接口和实现文件。我们所要做的就是在一个单一文件中定义一个类或者结构体,系统将会自动生成面向其他代码的外部接口。
小节包含内内容:
- 列表内容
- 类和结构体的对比
- 结构体和枚举是值类型
- 类是引用类型
- 类和结构体的选择
- 字符串、数组、字典类型的赋值与复制行为
分条详述
类和结构体对比
首先,Swift中类和结构体有很多共同点,共同之处在于(PS:关于属性、方法、下标脚本、构造过程、扩展和协议,其实后面都会说到,教材中提供了书中的具体位置链接):
- 定义属性用于存储值
- 定义方法用于提供功能
- 定义附属脚本用于访问值
- 定义构造器用于生成初始值
- 定义扩展用以增加默认实现的功能
- 事先协议以提供某种标准功能
与结构体相比,类还有如下的附加功能(PS:关于继承、类型转换、析构过程和自动引用计数,都是后面要说的内容):
- 继承允许一个类继承另一个类的特征
- 类型转换允许运行时检查和解释一个类实例的类型
- 解构器允许一个类实例解释任何其被分配的资源
- 引用计数允许对一个类多次引用
结构体总是通过被复制的方式在代码中传递,不使用引用计数
类和结构体有着类似的定义方式。通过关键字class和struct来分别表示类和结构体,并在一对大括号内定义他们的具体内容:
class SomeClass {// 类内部实现}struct SomeStructure {// Structure definition goes here}
每次定义一个新类,实际上都是定义了一个新的Swift类型,所以命名的时候注意规范,即命名时首字母大写,枚举也是如此。属性和方法名字首字母小写。命名时都要遵循驼峰命名法,并且起名字的时候尽量词能达意。
下面根据具体的例子来说明问题:// 结构体,描述一个显示器的分辨率struct Resolution {var width = 0var height = 0}// 类,描述一个视频显示器的特定模式class VideoMode {var resolution = Resolution()var interfaced = falsevar frameRate = 0.0var name: String?}
结构体和类都可以通过构造器语法来创建实例进行使用,构造器语法最简单的就是在类或者结构体名称后面添加小括号,构造时属性均会被初始化默认值。如:
// 构造结构体和类的实例let someResolution = Resolution()let someVideoMode = VideoMode()
可以通过点语法访问结构体或者类的属性或方法,并且当属性可变,即用var修饰时,可以改变属性值。相比于OC,Swift可以改变结构体或类的属性的子属性的值,而不需要为整个属性赋新值。
// 构造结构体和类的实例var someResolution = Resolution()let someVideoMode = VideoMode()// 点语法访问属性并修改值someResolution.height = 200someVideoMode.frameRate = 12.12someVideoMode.resolution.width = 300
注意,所有的结构体都有一个自动生成的成员逐一构造器,就是建立的时候为每个属性赋值。然而类并没有这个特性。只需在构造时输入左括号,自然会有提示。
结构体和枚举是值类型
值类型赋值给一个变量、常量或者被传递给一个函数时,其值会被拷贝,新拷贝的值和原来的值是完全隔离的,即他们的改变是独立的。在Swift中,整数、浮点数、布尔值、字符串、数组和字典,都是值类型,并且在底层都是以结构体的形式所实现。显然,结构体和枚举类型都是值类型。下面简单地代码很能说明问题:
// 值传递,对象以及所有属性都发生了拷贝let someResolution = Resolution(width: 1920, height: 1080)var anotherResolution = someResolutionanotherResolution.width = 2880anotherResolution.height = 1600// 通过输出结果,可以清晰体会到值传递是复制了另外一份数据print(someResolution.height,someResolution.width) // 1080 1920print(anotherResolution.height, anotherResolution.width) // 1600 2880
类是引用类型
与值类型不同,引用类型再被赋予到一个变量、常量或者被传递到一个函数时,其值不会被拷贝,因此引用是引的已存在的示例本身而不是拷贝。可以理解为多个指针指向同一个内存区域,任何一个指针对数据进行操作时,其他指针取到数据也是已经被修改的数据。如:
// 类是引用类型let someVideoMode = VideoMode()someVideoMode.frameRate = 2.05someVideoMode.resolution.height = 300let anotherVideoMode = someVideoModeanotherVideoMode.frameRate = 99.99anotherVideoMode.resolution.height = 2222// 展示现在两个类属性的值someVideoMode.frameRate // 99.9999someVideoMode.resolution.height // 2222anotherVideoMode.frameRate // 99.999anotherVideoMode.resolution.height // 2222
观察上面代码会看到一个比较迷惑的地方,那就是已经使用 let 设置类实例,为什么还能修改它的值呢?如果结构体使用 let 修饰,是无法更改里面的值的。为什么呢?为什么呢??原因很简单,因为类是引用类型,也就是说 someVideoMode 和 anotherVideoMode 本身并没有存储值,改变的仅仅是被引用的属性的值,他们本身的值并没有改变,所以可以用 let 修饰为常量来使用。
因为类是引用类型,有可能多个常量和变量幕后同时引用一个类实例。如果能够判断两个常量或者变量是否引用同一个类实例,将会很有帮助。为了达到这种目的,Swift内建了两个恒等运算符:
- 等价于(===)
- 不等价于(!==)
注意,”等价于“(用三个等号表示 ===) 与 等于(用两个等号表示 ==)的不同:
- “等价于”表示两个类类型(class type)的常量或者变量引用同一个类类型。
- “等于”表示两个实例的值“相等”或“相同”,判断时要遵照设计者定义的评判标准,因此,相对于“相等”来说,这事一种更合适的叫法。
类和结构体的选择
当考虑使用结构体合适使用类的时候,如果能用结构体,就果断使用结构体吧,尽量少的使用类。我在看atSwift第一届Swift开发者大会的时候,有好几个演讲人员都强调了这一点,能用结构体就不用类。在教材中,也是提供了什么情况下使用结构体效果更好。
按照通用的准则,当符合一条或多条以下条件时,请考虑使用结构体:- 该数据结构主要目的是用来封装少量相关简书数据值。
- 有理由预计该数据结构的实例再被赋值或传递时,封装的数据将会被拷贝而不是被引用。
- 该数据结构图中存储的值类型属性,也应该被拷贝,而不是被引用。
- 该数据结构不需要去继承另一个既有类型的属性或者行为。
举例来说,一下情境中适合使用结构体:
- 几何形状的大小,封装一个width属性和一个height属性,两者均为Double类型。
- 一定范围内的路径,封装一个start属性和一个length属性,两者均为Int类型。
- 三维坐标系内一点,封装 x/y/z 属性,三者均为Double类型。
教程中的话:在所有其他案例中,定义一个类,生成它的实例,并通过引用来管理和传递。实际上,这意味着绝大部分的自定义数据构造都应该是类,而非结构体。
其实,当教材和现实有了点冲突,我选择相信多用结构体。。。
关于Swift中的值传递和OC中的常用数据类型
在Swift中,所有值传递都是以拷贝的形式发生的,他们的低层都是由结构体实现的。这点和和OC中是不一样的。在Object-C中,NSString、NArray和NSDictionary中低层均以类的形式实现,它们在被赋值或者被传入参数时,不会发生值拷贝,而是传递现有实例的引用。
注意,以上对字符串、数组、字典的“拷贝”行为的描述,在代码中,好像拷贝行为看起来总会发生。然而,Swift在幕后只在绝对必要时才执行实际的拷贝。Swift管理所有值拷贝以确保性能最优化,所以没必要去回避赋值来保证性能最优化。
结束语
为啥现在写的这么慢了呢?是因为工作忙了么,毛线,就是过了新鲜劲,懒了。。。。。吾日三省吾身,早上吃什么,中午吃什么,晚上吃什么,就是忘了自省下为啥今天没坚持写点东西~
昨天晚上把权利的游戏第六季的前三集一次性看完了,也是过瘾,红巫女威武,囧哥威武!另外,感觉这张图的尺度好大~滑稽.jpg
另外,点击查看前几篇文章
- Swift-类和结构体(Class and Structures)(八)
- Swift类和结构体(Classes and Structures)
- Swift 类和结构体(Classes and Structures)
- Swift学习笔记9——类和结构体(Classes and Structures)
- 对照Java学习Swift--类和结构体(Classes and Structures)
- Swift-类和结构体(class&struct)
- Swift 类和结构体(八)
- 【Swift】学习笔记(八)——类和结构体
- Object-C--->Swift之(八)类和结构体
- Swift中结构体(Struct)和类(Class)的区别
- swift类和结构体(一)
- swift类和结构体(二)
- 结构体(Struct) 和 类(Class)
- 结构体(Struct) 和 类(Class)
- 寒城攻略:Listo 教你 25 天学会 Swift 语言 - 11 Class and Structures
- swift:类class是浅拷贝 结构体struct是深拷贝(代码理解)
- 四、控制结构和函数Control Structures and Functions
- 学习Swift笔记 (十)Swift的类和结构
- Activity
- 简单的网络状态监听
- scala学习笔记4
- java 折半查找 冒泡排序 选择排序
- 走走停停的日子,不要忘了努力,也不要忘了方向
- Swift-类和结构体(Class and Structures)(八)
- Android 自封装的各种类
- 解决cocoapods diff: /../Podfile.lock: No such file or directory
- Android--百度地图开发(二)
- NYOJ 38 布线问题
- 终端利器 - tmux配置与使用
- BZOJ4385: [POI2015]Wilcze doły
- hive1.2.1源码导入eclipse
- 软考程序员随笔-----5