如您所见,结构使我们可以合并各个数据片段以创建新内容,然后附加方法,以便我们可以操纵该数据。
今天,您将学习结构的一些更高级的功能,这些功能使它们更强大,包括访问控制,静态属性和惰性。是的,惰性——比尔·盖茨曾经说过:"我选择一个懒惰的人去做艰苦的工作,因为一个懒惰的人会找到一种简单的方法来做这件事。(I choose a lazy person to do a hard job, Because a lazy person will find an easy way to do it.)''如您所见,在Swift中,惰性是一项重要的性能优化。
提醒一下,所有这些东西都在SwiftUI中得到了广泛使用,因此值得花些时间来掌握它们,因为它们将从我们的第一个项目开始就被使用。
今天,您有6个一分钟的视频可供观看,并且像往常一样,完成每个视频后,都会进行一次简短的测试,以帮助您了解所教的内容。
1. 初始化器 Initializers – test
初始化是特殊的方法,提供了创建结构体的不同方法。默认情况下,所有结构体都带有一个默认的初始化器,称为成员初始化器(memberwise initializer)——这要求您在创建结构体时为每个属性提供一个值。
如果我们创建具有一个属性的User
结构体,则可以看到以下内容:
struct User {
var username: String
}
创建这些结构体之一时,必须提供用户名:
var user = User(username: "twostraws")
我们可以提供自己的初始化器来替换默认的初始化器。例如,我们可能希望将所有新用户创建为“匿名(Anonymous)”并打印一条消息,如下所示:
struct User {
var username: String
init() {
username = "Anonymous"
print("Creating a new user!")
}
}
您不必在初始化器之前编写func
,但需要确保在初始化结束之前所有属性都具有一个值。
现在我们的初始化程序不接受任何参数,我们需要创建如下结构:
var user = User()
user.username = "twostraws"
2. 引用当前实例 Referring to the current instance – test
在方法内部,您会得到一个称为self
的特殊常量,该常量指向当前正在使用的该结构体的任何实例。当您创建具有与属性相同的参数名称的初始化器时,此self
值特别有用。
例如,如果您创建一个具有name
属性的Person
结构体,然后尝试编写一个接受name
参数的初始化器,那么self
可以帮助您区分该属性和参数—— self.name
是指该属性,而name
是指该属性参数。
代码如下:
struct Person {
var name: String
init(name: String) {
print("\(name) was born!")
self.name = name
}
}
3. 懒加载属性 Lazy properties – test
作为性能优化,Swift允许您仅在需要时才创建一些属性。例如,考虑以下FamilyTree
结构体——并没有做很多事,但是从理论上讲,为某人创建家谱需要很长时间:
struct FamilyTree {
init() {
print("Creating family tree!")
}
}
我们可以将该FamilyTree
结构体用作Person
结构体中的属性,如下所示:
struct Person {
var name: String
var familyTree = FamilyTree()
init(name: String) {
self.name = name
}
}
var ed = Person(name: "Ed")
但是,如果我们并不总是需要某个人的家谱怎么办?如果我们将lazy
关键字添加到familyTree
属性,则Swift仅在首次访问时才会创建FamilyTree
结构体:
lazy var familyTree = FamilyTree()
因此,如果您想看到“Creating family tree!”消息,您需要至少访问一次该属性:
ed.familyTree
4. 静态属性和方法 Static properties and methods – test
到目前为止,我们创建的所有属性和方法都属于单个结构体实例,这意味着,如果我们有一个Student
结构体,我们可以创建多个学生实例,每个实例都具有各自的属性和方法:
struct Student {
var name: String
init(name: String) {
self.name = name
}
}
let ed = Student(name: "Ed")
let taylor = Student(name: "Taylor")
您也可以要求Swift在结构体的所有实例之间共享特定的属性和方法,方法是将它们声明为静态的(static)。
要尝试此操作,我们将向Student
结构体添加一个静态属性,以存储班上有多少学生。每次创建新学生时,我们都会向其中添加一个:
struct Student {
static var classSize = 0
var name: String
init(name: String) {
self.name = name
Student.classSize += 1
}
}
因为classSize
属性属于该结构体本身而不是该结构的实例,所以我们需要使用Student.classSize
来读取它:
print(Student.classSize)
5. 访问控制 Access control – test
访问控制使您可以限制可以使用属性和方法的代码。这很重要,因为例如,您可能希望阻止人们直接读取属性。
我们可以创建一个具有id
属性的Person
结构体,以存储其社会保险号:
struct Person {
var id: String
init(id: String) {
self.id = id
}
}
let ed = Person(id: "12345")
创建该人后,我们可以将其id
设为私有,这样您就无法从struct
外部读取它——尝试编写·ed.id·根本行不通。
只需使用private
关键字,如下所示:
struct Person {
private var id: String
init(id: String) {
self.id = id
}
}
现在,只有Person
内部的方法可以读取id
属性。例如:
truct Person {
private var id: String
init(id: String) {
self.id = id
}
func identify() -> String {
return "My social security number is \(id)"
}
}
另一个常见的选择是public
,它允许所有其他代码使用该属性或方法。
(PS Swift的访问控制关键字有如下五种):
关键字 | 简单描述 |
---|---|
open | 公开权限, 最高的权限, 可以被其他模块访问, 继承及复写。 |
public | 公有访问权限,类或者类的公有属性或者公有方法可以从文件或者模块的任何地方进行访问。无法在其他模块被复写方法/属性或被继承。 |
fileprivate | 可以在同一个物理文件中访问。如果超出该物理文件,属性和方法就不能被访问。 |
private | 私有访问权限,被private修饰的类或者类的属性或方法可以在同一个物理文件中的同一个类型(包含extension)访问。如果超出该物理文件或不属于同一类型,那么有着private访问权限的属性和方法就不能被访问。 |
internal | Swift默认访问权限,模块内部可以访问,超出模块内部就不能被访问了。 |
6. 结构体: 总结 Structs summary – test
您已经完成了本系列第七部分,因此,让我们总结一下:
1、您可以使用结构体创建自己的类型,这些结构体可以具有自己的属性和方法。
2、您可以使用存储属性或使用计算属性即时计算值。
3、如果要在方法内部更改属性,则必须将其标记为mutating
。
4、初始化器是创建结构体的特殊方法。默认情况下,您将获得一个成员初始化器,但是如果创建自己的初始化器,则必须为所有属性赋予一个值。
5、使用self
常量可以在方法内部引用结构体的当前实例。
6、lazy
关键字告诉Swift仅在首次使用属性时才创建属性。
7、您可以使用static
关键字在结构体的所有实例之间共享属性和方法。
8、访问控制使您可以限制哪些属性和方法的代码是可以外部使用的。
这是Swift的另一个重要主题——干得好!现在,做一些聪明的事情,并在网上发布进度:它迫使您用自己的话来写这些事情,并鼓励您继续明天。
赏我一个赞吧~~~