本文介绍: TED演讲的8个秘诀:学习18分钟高效表达-重点笔记Swift基础入门知识学习(13)-枚举(列举)-讲给你懂懂目录类与结构体的比较类与结构实例取得属性结构类型成员逐一建构器结构体和列举是值类型类是参考类型恒等运算子请注意===与==的不同使用类或结构体?当符合一条或多条以下条件时,请考虑构建结构体:举例来说,以下情况中适合使用结构体:类(class)及结构体(structure),可以让你将多个相关函数及值储存在内,以及更多的特性。目前你可以稍微把类与结构体看为进阶豪华版的函数。类与.

TED演讲的8个秘诀:学习18分钟高效表达-重点笔记

Swift基础入门知识学习(12)-枚举(列举)-讲给你懂


理解难度
★★★★☆
实用程度
★★★☆☆

类(class)及结构体(structure),可以让你将多个相关函数及值储存在内,以及更多的特性。目前你可以稍微把类与结构体看为进阶豪华版的函数

类与结构体的比较

类及结构体有很多相同的地方,如下

与结构体相比,类还有以下的其他功能

定义一个类及结构体分别要使用classstruct关键字,并接着一组大括号{ },格式如下

class 类名称 {
类内的属性、方法及其他可以定义在内的特性
}

struct 结构体名称 {
结构体内的属性、方法及其他可以定义在内的特性
}

以下是定义结构体与类的例子

struct CharacterStats {
    var hp = 0.0
    var mp = 0.0
}
class GameOne {
    var stats = CharacterStats()
    var attackSpeed = 1.0
    var name: String?
}

上述程式中,定义了一个名为CharacterStats的结构体来描述一个游戏角色状态这个结构体包含两个属性(属性即为储存在类或结构体内的常数或变数):hp跟mp,分别表示角色血量与法力的最大值。当这两个属性被初始化为0.0时,会被自动推断为Double类型

接着定义了一个名为GameOne的类,描述一个游戏角色基本资讯,这个类包含了三个属性,第一个角色状态,会被初始化为一个CharacterStats结构体的实例,其后两个属性为攻速及名字,攻速有预设值1.0,名字则为一个可选类型String?,会被自动指派为一个预设值nil表示一开始没有name值。

类与结构体五个重要区别

  1. 类不附带合成成员初始化器。
  2. 一个类可以构建在另一个类上(“继承”),获得属性和方法。
  3. 结构体的副本始终是唯一的,而类的副本实际上指向相同共享数据
  4. 类有取消初始化器,这些方法是在类实例销毁调用的方法,但结构体没有
  5. 常量类中变量属性可以自由修改,但常量结构中的变量属性不能修改

类与结构体实例

定义类与结构体,就像是给了一个固定的规格,譬如说明一个游戏角色会有血量、法力、攻速、名字这些资讯,但使用上,必须依照这个规格(即类或结构体)来实际建立一个角色这个动作就是生成类或结构体的实例(instance)。

实例有些地方会翻译实体,同样都是指instance
类与结构体都使用建构器语法生成实体,建构器最简单的形式就是在类或结构体名称后面加上一个小括号()语法,这种方式建立的实例,其内的属性都会被初始化为预设值,如下

let someStats = CharacterStats()
let someGameCharacter = GameOne()

上述程式中,someStats就是一个CharacterStats结构体的实例,someGameCharacter则为一个GameOne类的实例。

可以看到生成实例的方式与呼叫函数相似,所以习惯上两种命名方式会不一样,一个使用大驼峰式命名法,另一个使用小驼峰式命名法,来作区别

取得属性

使用点语法(dot syntax)可以取得实例的属性(property)。规则为实例名称后加上一个点号.,然后紧接着属性名称如下

// 这边使用前面定义的 CharacterStats 结构体 及生成的实例 someStats
// 因为没有初始值 所以会使用预设值 这边会印出:someStats 血量最大值为0.0
print("someStats 血量最大值为(someStats.hp)")

你可以连结多个点语法直接取得子属性,像是someGameCharacter中stats属性的hp属性,如下:

// 这边使用前面定义的 GameOne 类
// 及其生成的实例 someGameCharacter
// 印出:血量最大值为0.0
print("血量最大值为(someGameCharacter.stats.hp)")

也可以将新的值指派给实例的属性,如下:

// 将 someGameCharacter 的血量最大值指派为 500
someGameCharacter.stats.hp = 500
// 再次印出 即会变成:500.0
print(someGameCharacter.stats.hp)

结构体类型的成员逐一建构器

所有结构体都有一个自动生成的成员逐一建构器(memberwise initializer),当要生成一个结构体的实例时,用来初始化实例内的属性,如下:

// 这边使用前面定义的 CharacterStats 结构体 生成新的实例 someoneStats
let someoneStats = CharacterStats(hp: 120, mp: 100)

// 印出:120.0
print(someoneStats.hp)

结构体和列举是值类型

值类型(value type)在被指派给一个变数、常数或被传递给一个函数时,实际上操作的是其拷贝(copy)。指派或传递后,两者的值即各自独立,不会互相影响

在前面章节中,其实已经大量使用了值类型。实际上,在 Swift 中,所有的基本类型:整数浮点数、布林值、字串、阵列和字典,都是值类型,并且背后都是以结构体的形式实作。

结构体和列举也都是值类型,代表它们的实例及其内任何值类型的属性,在被指派或传递时都会被复制例子如下:

// 这边使用前面定义的 CharacterStats 结构体
var oneStats = CharacterStats(hp: 120, mp: 100)
var anotherStats = oneStats

// 这时修改 anotherStats 的 hp 属性
anotherStats.hp = 300
// 可以看出来已经改变了 印出:300.0
print(anotherStats.hp)

// 但 oneStats 的属性不会改变
// 仍然是被生成实例时的初始值 印出:120.0
print(oneStats.hp)

在oneStats被指派给anotherStats时,其实是将oneStats内的值进行拷贝(copy),接着将拷贝的资料储存给新的实例anotherStats,两者是完全独立的实例,彼此不会互相影响

类是参考类型

与值类型不同,参考类型(reference type)在被指派给一个变数、常数或被传递给一个函数时,操作的不是其拷贝,而是已存在的实例本身。例子如下:

// 这边使用前面定义的 GameOne 类
let archer = GameOne()
archer.attackSpeed = 1.5
archer.name = "弓箭手"

// 指派给一个新的常数
let superArcher = archer
// 并修改这个新实例的属性 attackSpeed
superArcher.attackSpeed = 1.8

// 可以看到这边印出的都为:1.8
print("archer 的攻速为 (archer.attackSpeed)")
print("superArcher 的攻速为 (superArcher.attackSpeed)")

从上述程式可以知道archer跟superArcher实际上是对同一个实例做操作。也就是同一个实例的两个不同名称

有一点要注意的是,可以看到archer跟superArcher都被宣告为常数(使用let宣告),但依然可以改变其内的属性archer.attackSpeed跟superArcher.attackSpeed,因为这两个常数储存的是一个GameOne类实例的参考(参考其在记忆空间配置位置),而不是储存这个实例,所以这个实例的attackSpeed属性可以被修改,但不会修改到常数的值。

恒等运算子

因为类是参考类型,可能有多个常数和变数在后台同时参考某一个类实例,所以 Swift 提供了两个恒等运算子能够判断两个变数或常数是不是参考同一个类实例:

等价于 ===
不等价于 !==

以下是一个例子

// 使用前面宣告的两个常数 archer 与 superArcher
if archer === superArcher {
    print("没错!!!是同一个类实例")
}

请注意=的不同

使用类或结构体?

类与结构体有很多相似的地方,要如何决定每个资料建构要定义为类还是结构体,可以参考以下原则

  1. 需要封装资料量较少且较简单
  2. 在指派或传递这个实例时,有特别需求这个资料是会被拷贝而不是参考。
  3. 结构体中储存的值类型属性,也希望是会被拷贝而不是参考。
  4. 需要继承另一个已存在类型的属性或行为

如果符合上述一条或以上原则,则建议定义为结构体,其余则是定义为类。
所以实际上,大部分自定义资料建构都应该使用类。

当符合一条或多条以下条件时,请考虑构建结构体:

  1. 结构体的主要目的是用来封装少量相关简单数据值。
  2. 有理由预计一个结构体实例在赋值传递时,封装的数据将会被拷贝而不是被引用
  3. 任何在结构体中储存的值类型属性,也将会被拷贝,而不是被引用
  4. 结构体不需要继承另一个已存在类型的属性或者行为

举例来说,以下情况中适合使用结构体:

  1. 几何形状大小,封装一个width属性和height属性,两者均为Double类型。
  2. 一定范围内的路径,封装一个start属性和length属性,两者均为Int类型。
  3. 三维坐标系内一点,封装xy和z属性,三者均为Double类型。

Swift基础入门知识学习(14)-属性-讲给你懂

高效阅读-事半功倍读书法-重点笔记-不长,都是干货

原文地址:https://blog.csdn.net/weixin_42385177/article/details/121710437

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_36770.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注