在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类和结构体的更多相关文章

  1. swift 类和结构体

    1:类和结构体定义 类和结构体分别通过关键字class 和struct定义. swift的编码风格是类class和结构体struct名字使用大写字母开头的匈牙利表示法,相反的.类的方法和属性则用小写字 ...

  2. swift 类 与 结构体

    这两天突然有人问我  swift里面 类和 结构体  有什么区别? 说实在的本人目前不太看好swift,相信很多人也是,oc 都 很成熟了. 本人目前不打算深入了解swift的原因swift  语言 ...

  3. Swift类与结构体

    类和结构体有很多共性: 定义属性存储数据 定义方法执行功能处理 定义下标,通过下标访问他们的值 初始化他们的状态 通过扩展(Extension)扩展其功能 遵守协议(Protocol),协议提供一种特 ...

  4. Swift: 类与结构体

    对比类与结构体 类与结构体有许多的相同点,它们都可以: 定义属性来存储值: 定义方法来提供功能: 定义下标操作: 定义初始化函数: 扩展它的默认的实现: 遵从协议: 类有一些额外的能力,但是结构体没有 ...

  5. Swift类和结构体定义-备

    Swift中的类和结构体定义的语法是非常相似的.类使用class关键词定义类,使用struct关键词定义结构体,它们的语法格式如下: class 类名 { 定义类的成员 } struct 结构体名 { ...

  6. Swift 类和结构体的简单认识

    类和结构体的共同点: 定义属性用于存储值 定义方法用于提供功能 定义附属脚本用于访问值 通过拓展增加默认实现的功能 定义构造器用于生成初始化值 实现协议以提供某种标准功能 类是引用类型 结构体是值类型 ...

  7. Swift - 类和结构体的区别

    类和结构体有许多相同之处,也有许多不同之处. 二者区别如下: 1,类可以继承和扩展,结构体不可以 2,可以让一个类的实例来反初始化,释放存储空间,结构体做不到 3,类的对象是引用类型,而结构体是值类型 ...

  8. swift学习笔记3——类、结构体、枚举

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  9. 【Swift学习】Swift编程之旅---类和结构体(十三)

    与其他编程语言所不同的是,Swift 并不要求你为自定义类和结构去创建独立的接口和实现文件.你所要做的是在一个单一文件中定义一个类或者结构体,系统将会自动生成面向其它代码的外部接口. 注意:通常一个类 ...

随机推荐

  1. win10 sublime license

    —– BEGIN LICENSE —– TwitterInc 200 User License EA7E-890007 1D77F72E 390CDD93 4DCBA022 FAF60790 61AA ...

  2. app后端开发系列文章文件夹

    一点废话 每个程序猿心中,都有一个大牛梦.我们在晨曦之光中敲击着代码,在寒冬覆雪中思考着0与1. 夏练三伏 冬练三九这说的就是我们这群[江湖]中人.在这里我们门派林立,C语言派历史悠久,在程序界就是嵩 ...

  3. ajax——dom对xml和html的操作

    上篇文章说到了dom的基础,dom能够操作xml和html,这次主要写利用dom的api去如何去操作xml和html文档. dom操作xml dom操作xml文档之前必须把xml文档装载到xml do ...

  4. PHP compact() 函数

    Compact ---- 创建一个包含变量名和它们的值的数组: <?php $firstname = "Bill"; $lastname = "Gates" ...

  5. python(19)- 列表生成式和生成器表达式练习Ⅰ

    列表表达式 程序一: 常规写法: egg_list=[] for i in range(100): egg_list.append('egg%s' %i) print(egg_list) 列表表达式写 ...

  6. soapUI学习笔记---断言的小使用

    转自:http://www.cnblogs.com/duimianyoushan/p/4274791.html 以下示例在soapUI 4.5中进行.刚开始学soapUI的使用,记录下以免忘记 1.创 ...

  7. FFmpeg源码简单分析:结构体成员管理系统-AVOption

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  8. WPF 的 MVVM

    Model——View——ViewModel http://www.cnblogs.com/fdyang/p/3877309.html

  9. 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状态,本人刚接触 ...

  10. 我对C语言输入和输出和一些其他的疑惑点

    gets(字符串数组) 用来接收字符串数组 等同于 scanf("%s",字符串数组名)  需要说的一点是 字符串的数组名 就表示数组的第一个元素的地址 所以加不加&取地址 ...