Swift类和结构体
在C++中,相信不会有太多人去详细考究结构体和类的区别,因为二者关系实在不大。但在Swift中,结构体和类的关系非常大,它们的组成部分都包括:初始化器、实例方法、实例属性、类型属性、类型方法等等;二者也自然有很多的不同点,最大的不同点要数「类是引用类型,结构体是值类型」。本文着重对比阐述类和结构体的本质区别和它们的使用。
类和结构体对比
在Swift中,类和结构体有很多的共同点,包括:
- Define properties to store values.
- Define methods to provide functionality.
- Define subscripts to provide access to their values using subscript syntax.
- Define initializers to set up their initial state.
- Be extended to expend their functionality beyond a default implementation.
- Conform to protocols to provide standard functionality of a certain kind.
和结构体相比,类还具有一些结构体不具备的特性:
- Inheritance enables one class to inherit the characteristics of another.(结构体是不允许继承或被继承的)
- Type casting enables you to check and interpret the type of a class instance at runtime.(结构体不存在多态,自然不存在所谓的「类型转换」了)
- Deinitializers enable an instance of a class to free up any resources it has assigned.
- Reference counting allows more than one reference to a class instance.
类和结构体的定义
类和结构体有着类似的定义方式。我们通过关键字class和struct来分别表示类和结构体,并在一对大括号{}
中定义它们的具体内容,如下定义了一个结构体类型Resolution(用来描述一个显示器的像素分辨率)和一个类类型VideoMode(用来描述一个视频显示器的特定模式):
struct Resolution {
var width =
var height =
}
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
定义结构体和类实例语法几乎一样:
let someResolution = Resolution()
let someVideoMode = VideoMode()
和其他大多数语言一样,访问实例的属性使用.
操作符。但是与OC不同的是,Swift允许直接设置结构体属性的子属性(在OC中可不允许),如下:
println("The width of someVideoMode is \(someVideoMode.resolution.widt
h)")
// 输出 "The width of someVideoMode is 0"
someVideo.resolution.width =
println("The width of someVideoMode is now \(someVideoMode.resolution.
width)")
// 输出 "The width of someVideoMode is now 1280"
结构体的逐一成员构造器
Swift为类和结构体都提供了默认的初始化构造器,其中有一个为结构体特别提供的默认构造器叫「逐一成员构造器」(memberwise initializer)。简而言之,使用该构造器,在创建实例时可以通过属性的名称设置它们的属性值,如下:
let vga = resolution(width:, height:)
更多关于结构体的「逐一成员构造器」信息,参考这里。
值类型和引用类型
类是引用类型
众所周知,类类型是「引用类型」。换句话说,对类类型变量赋值(譬如函数/方法的参数传值、返回值、变量赋值等),实际上操作的只是对象指针的拷贝。
结构体和枚举都是值类型
与「引用类型」对应的是「值类型」。值类型被赋予给一个变量,常数或者本身被传递给一个函数的时候,实际上操作的是对其进行拷贝。
在Swift中,所有的基本类型都是值类型。换句话说,整型、浮点型、布尔值、字符串、数组、set、字典都是值类型,更进一步说,它们都是「结构体」类型。
恒等运算符
考虑到类是引用类型,有可能有多个常量或变量在后台同时引用同一个实例(当然,这对属于值类型的结构体和枚举而言是不成立的)。所以在很多时候需要判断两个常量或者变量是否引用同一个类实例,Swift为我们提供了两个运算符===
和!==
,它们被称为「恒等运算符」(Identity Operators)。关于它们的用法就不啰嗦了,一眼就能看出来。
类和结构体的选择
相对于其他语言譬如C++,Swift中赋予了结构体更强大的功能,它和类类型有非常多的相似之处,都可以用来自定义数据类型,那么该如何选用呢?
结构体实例总是通过「值传递」,类实例总是通过「引用传递」。这意味着二者适用于不同的任
务。按照通用的准则,当符合一条或多条以下条件时,请考虑构建结构体:
- 结构体的主要目的是用来封装少量相关简单数据值;
- 有理由预计一个结构体实例在赋值或传递时,封装的数据将会被拷贝而不是被引用;
- 任何在结构体中储存的值类型属性,也将会被拷贝,而不是被引用;
- 结构体不需要去继承另一个已存在类型的属性或者行为;
P.S:个人觉得,有了一定的使用经历之后,这个问题便不再是问题了,可能会变成一种下意识。
集合类型的赋值和拷贝行为
姑且也把String认为是集合类型吧!
在OC中,NSString、NSArray、NSSet、NSDictionary以及相关类型都是类类型,因此,在传递过程中,它们的传递方式默认情况都是引用传递(对于属性,如果指定copy修饰词则有所不同,相对而言,比较复杂)。
但是在Swift中,正如前文所述,String、Array、Set、Dictionary的本质都是「结构体」。无论在什么场合,它们的传递方式都是值传递。官方文档是这么描述的:
Swift’s String, Array, and Dictionary types are implemented as structures. This means that strings, arrays, and dictionaries are copied when they are assigned to a new constant or variable, or when they are passed to a function or method.
P.S:在第一个版本的《The Swift Programming Language》中有不同的描述,大概的意思是:
Swift中数组(Array)和字典(Dictionary)类型均以结构体的形式实现。然而当数组被赋予一个常量或变量,或被传递给一个函数或方法时,数组(以及字典)的拷贝行为和其它结构体有些许不同。在Swift的后台中,只有确有必要,实际(actual)拷贝才会被执行。Swift管理所有的值拷贝以确保性能最优化的性能,所以你也没有必要去避免赋值以保证最优性能。
P.P.S:上述这段话摘自《The Swift Programming Language》第一个版本中译版。可以看出,相对于第一个版本,当下Swift(1.2版本)做了一些修改,简化了设计理念,理解上也更容易一些。
Swift类和结构体的更多相关文章
- swift 类和结构体
1:类和结构体定义 类和结构体分别通过关键字class 和struct定义. swift的编码风格是类class和结构体struct名字使用大写字母开头的匈牙利表示法,相反的.类的方法和属性则用小写字 ...
- swift 类 与 结构体
这两天突然有人问我 swift里面 类和 结构体 有什么区别? 说实在的本人目前不太看好swift,相信很多人也是,oc 都 很成熟了. 本人目前不打算深入了解swift的原因swift 语言 ...
- Swift类与结构体
类和结构体有很多共性: 定义属性存储数据 定义方法执行功能处理 定义下标,通过下标访问他们的值 初始化他们的状态 通过扩展(Extension)扩展其功能 遵守协议(Protocol),协议提供一种特 ...
- Swift: 类与结构体
对比类与结构体 类与结构体有许多的相同点,它们都可以: 定义属性来存储值: 定义方法来提供功能: 定义下标操作: 定义初始化函数: 扩展它的默认的实现: 遵从协议: 类有一些额外的能力,但是结构体没有 ...
- Swift类和结构体定义-备
Swift中的类和结构体定义的语法是非常相似的.类使用class关键词定义类,使用struct关键词定义结构体,它们的语法格式如下: class 类名 { 定义类的成员 } struct 结构体名 { ...
- Swift 类和结构体的简单认识
类和结构体的共同点: 定义属性用于存储值 定义方法用于提供功能 定义附属脚本用于访问值 通过拓展增加默认实现的功能 定义构造器用于生成初始化值 实现协议以提供某种标准功能 类是引用类型 结构体是值类型 ...
- Swift - 类和结构体的区别
类和结构体有许多相同之处,也有许多不同之处. 二者区别如下: 1,类可以继承和扩展,结构体不可以 2,可以让一个类的实例来反初始化,释放存储空间,结构体做不到 3,类的对象是引用类型,而结构体是值类型 ...
- swift学习笔记3——类、结构体、枚举
之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...
- 【Swift学习】Swift编程之旅---类和结构体(十三)
与其他编程语言所不同的是,Swift 并不要求你为自定义类和结构去创建独立的接口和实现文件.你所要做的是在一个单一文件中定义一个类或者结构体,系统将会自动生成面向其它代码的外部接口. 注意:通常一个类 ...
随机推荐
- win10 sublime license
—– BEGIN LICENSE —– TwitterInc 200 User License EA7E-890007 1D77F72E 390CDD93 4DCBA022 FAF60790 61AA ...
- app后端开发系列文章文件夹
一点废话 每个程序猿心中,都有一个大牛梦.我们在晨曦之光中敲击着代码,在寒冬覆雪中思考着0与1. 夏练三伏 冬练三九这说的就是我们这群[江湖]中人.在这里我们门派林立,C语言派历史悠久,在程序界就是嵩 ...
- ajax——dom对xml和html的操作
上篇文章说到了dom的基础,dom能够操作xml和html,这次主要写利用dom的api去如何去操作xml和html文档. dom操作xml dom操作xml文档之前必须把xml文档装载到xml do ...
- PHP compact() 函数
Compact ---- 创建一个包含变量名和它们的值的数组: <?php $firstname = "Bill"; $lastname = "Gates" ...
- python(19)- 列表生成式和生成器表达式练习Ⅰ
列表表达式 程序一: 常规写法: egg_list=[] for i in range(100): egg_list.append('egg%s' %i) print(egg_list) 列表表达式写 ...
- soapUI学习笔记---断言的小使用
转自:http://www.cnblogs.com/duimianyoushan/p/4274791.html 以下示例在soapUI 4.5中进行.刚开始学soapUI的使用,记录下以免忘记 1.创 ...
- FFmpeg源码简单分析:结构体成员管理系统-AVOption
===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...
- WPF 的 MVVM
Model——View——ViewModel http://www.cnblogs.com/fdyang/p/3877309.html
- http://www.cnblogs.com/yycxbjl/archive/2010/04/20/1716689.html
http://www.cnblogs.com/yycxbjl/archive/2010/04/20/1716689.html PS: 开发工具 VS2010, 所有工程都为Debug状态,本人刚接触 ...
- 我对C语言输入和输出和一些其他的疑惑点
gets(字符串数组) 用来接收字符串数组 等同于 scanf("%s",字符串数组名) 需要说的一点是 字符串的数组名 就表示数组的第一个元素的地址 所以加不加&取地址 ...