Swift结构体和类详解

一、类和结构体的对比

(一)、类和结构体的相同点
  • 定义存储值的属性;
  • 定义提供功能的方法;
  • 定义下标以使用下标语法提供对其值的访问;
  • 定义初始化器来设置其初始状态;
  • 通过扩展增加新功能;
  • 遵守协议来提供某种标准功能;
(二)、类和结构体的不同点

类具有结构体不具备的其他功能:

  • 继承使一个类可以继承另一个类的特性;
  • 类型转换使你可以在运行时检查和解释类实例的类型;
  • 析构器使类的实例可以释放它已分配的任何资源;
  • 引用计数器允许对一个类实例的多个引用;
(三)、如何选择类和结构体

在应用程序中存储数据和建模行为时,结构和类是很好的选择,但是它们的相似性使得很难正确选择使用哪种数据类型。
考虑以下建议,可以帮助你在向应用程序中添加新数据类型时选择合适的数据类型。

  • 默认情况下使用结构;
  • 在需要Objective-C互操作性时使用类;
  • 当您需要控制正在建模的数据的标识时,请使用类;
  • 使用结构体和协议通过共享实现来采用行为;
    参考资料:
  • 如何选择类和结构体

二、定义语法

类和结构体的定义语法:

struct SomeStructure {
    // structure definition goes here
}
class SomeClass {
    // class definition goes here
}

定义类和结构体的示例:

struct Resolution {
    var width = 0
    var height = 0
}
class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name: String?
}

二、结构体的全能初始化器

所有结构都有一个自动生成的成员初始化器,可以使用它初始化新结构实例的所有成员属性。

let vga = Resolution(width: 640, height: 480)

与结构不同,类实例不接收默认的全能初始化器。

三、结构体和枚举是值类型

值类型是一种类型,其值在被赋值给变量或常量时被复制,或者在传递给函数时被复制。
Swift中的所有的基本类型:整数、浮点数、布尔、字符串、 数组 和 字典都是值类型,并且在底层的实现是结构体。同时Swift中所有的枚举和结构体也是值类型,这意味着我们创建的任何结构和枚举实例,以及作为它们属性的任何值类型,在代码中传递时始终会被复制。

注意:标准库中定义的集合(如数组,字典和字符串)使用了优化来降低复制时的性能消耗。 这些集合不是立即复制,而是共享内存,其中元素存储在原始实例和任何副本之间。 如果修改了这个集合的其中一个副本,则在修改之前复制元素。 你在代码中看到的行为总是好像立即发生了复制。

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
cinema.width = 2048
print("cinema is now \(cinema.width) pixels wide")
// Prints "cinema is now 2048 pixels wide"

print("hd is still \(hd.width) pixels wide")
// Prints "hd is still 1920 pixels wide"

上述示例中,首先声明了一个常量hd,将其设置为一个Resolution类型的结构体实例。然后又声明了一个变量cinema,将其设置为hd当前的值。由于Resolution是一个结构体类型,因此会生成该实例的副本,并将新的副本分配给cinema。尽管hdcinema现在有相同的widthheight,但是在内存中它们是两个完全不同的实例。因此当修改cinema中的width属性时,对hd中的width属性并没有影响。它们在内存中的分配如下图所示:

sharedStateStruct_2x.png

同理,枚举也是相同的。

enum CompassPoint {
    case north, south, east, west
    mutating func turnNorth() {
        self = .north
    }
}
var currentDirection = CompassPoint.west
let rememberedDirection = currentDirection
currentDirection.turnNorth()

print("The current direction is \(currentDirection)")
print("The remembered direction is \(rememberedDirection)")
// Prints "The current direction is north"
// Prints "The remembered direction is west"

四、类是引用类型

与值类型不同,引用类型在分配给一个变量或常量,或者传递给函数时不会被拷贝。 不是使用拷贝的对象,而是使用对同一个现有实例对象的引用。

let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0

print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
// Prints "The frameRate property of tenEighty is now 30.0"

上述示例中,由于类是引用类型,tenEightyalsoTenEighty都引用相同的VideoMode实例对象。实际上,它们只是同一个实例对象的两个不同名称,如下图所示:

sharedStateClass_2x.png

五、相等性判断

因为类是引用类型,所以多个常量和变量在内存中可能引用的是同一个类的实例对象。 而对于结构和枚举来说情况并非如此,因为它们在分配给常量或变量或传递给函数时总是被复制。
有时可以判断两个常量或变量是否指向同一个类的相同实例对象。 为了实现这一点,Swift提供了两个身份运算符:

  • 相同的 (===)
  • 不完全相同(!==)
    使用这些运算符可以检查两个常量或变量是否引用同一个实例对象:
if tenEighty === alsoTenEighty {
    print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")
}
// Prints "tenEighty and alsoTenEighty refer to the same VideoMode instance."

===并不等同于 =====意味着class类型的两个常量或变量引用完全相同的类实例对象。而==意味着两个实例在值上被认为是相等的或等价的,对于相等的某些适当含义,由类型的设计者定义。
当自定义结构和类时,你有责任确定两个实例相等的条件。 在等价运算符中描述了定义自己的“等于”和“不等于”运算符的实现的过程。 Equivalence Operators

六、指针

如果你熟悉C,C ++或Objective-C,你可能知道这些语言都使用指针来引用内存中的地址。 Swift中的常量或变量对某个引用类型的实例的引用,类似于C中的指针,但是它不是指向内存中地址的直接指针,并且也不需要你使用星号(*)来指明正在创建一个引用。 相反,这些引用的定义与Swift中的任何其他常量或变量一样。 标准库提供了指针和缓冲区类型,如果需要直接与指针交互,可以使用这些类型- 请参阅手动内存管理

七、其他专题模块

Swift 4.2 基础专题详解

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,727评论 2 9
  • Swift语法基础(五)-- (类和结构体、属性、方法) 本章将会介绍 类和结构体对比结构体和枚举是值类型类是引用...
    寒桥阅读 1,078评论 0 1
  • 人一生会遇到很多人,有些人喜欢在你人生中来来去去,走了又来,来了又走,也有一些人出现在你的人生历程中就为了给你一个...
    付小悦阅读 181评论 0 0
  • 今天的文章题目不好取,母爱的范围太大也不知道怎么样概括。在我的生长环境中,接收到的母爱次数比父爱多,这与我的家庭...
    晴天小站阅读 240评论 2 0
  • 我们注重的不应该是软件本身, 而是其中生活积累沉淀后的思想,持续关注你的大脑,是在归纳、整理、纠错,更是优化思绪的...
    菜五阅读 184评论 0 1