IOS Swift 从入门到精通: 结构体的访问控制、静态属性和惰性

文章目录

初始化器

初始化器是一种特殊方法,可提供创建结构体的不同方式。所有结构体都默认带有一个初始化器,称为成员初始化器- 它会要求您在创建结构体时为每个属性提供一个值。

User如果我们创建一个具有一个属性的结构,你就会看到这一点:

swift 复制代码
struct User {
    var username: String
}

当我们创建其中一个结构时,我们必须提供一个用户名:

swift 复制代码
var user = User(username: "twostraws")

我们可以提供自己的初始化程序来替换默认的初始化程序。例如,我们可能希望将所有新用户创建为"匿名"并打印一条消息,如下所示:

swift 复制代码
struct User {
    var username: String

    init() {
        username = "Anonymous"
        print("Creating a new user!")
    }
}

您不需要在初始化程序之前写入func,但是您需要确保在初始化程序结束之前所有属性都有一个值。

现在我们的初始化程序不接受任何参数,我们需要像这样创建结构:

swift 复制代码
var user = User()
user.username = "twostraws"

引用当前实例

在方法内部,您会得到一个名为 的特殊常量self,它指向当前正在使用的结构的任何实例。self当您创建具有与属性相同参数名称的初始化程序时,此值特别有用。

例如,如果您创建一个具有属性Person的结构体name,然后尝试编写一个接受name参数的初始化程序,self可以帮助您区分属性和参数------ self.name引用属性,而引用name参数。

代码如下:

swift 复制代码
struct Person {
    var name: String

    init(name: String) {
        print("\(name) was born!")
        self.name = name
    }
}

惰性属性

作为一项性能优化,Swift 允许您仅在需要时创建某些属性。例如,考虑这个FamilyTree结构体------它没有太多作用,但理论上为某人创建家谱需要很长时间:

swift 复制代码
struct FamilyTree {
    init() {
        print("Creating family tree!")
    }
}

我们可以将该FamilyTree结构用作结构内的属性Person,如下所示:

swift 复制代码
struct Person {
    var name: String
    var familyTree = FamilyTree()

    init(name: String) {
        self.name = name
    }
}
swift 复制代码
var ed = Person(name: "Ed")

但是如果我们并不总是需要某个人的家谱呢?如果我们将关键字添加lazy到属性中familyTree,那么 Swift 将仅FamilyTree在第一次访问时创建结构体:

swift 复制代码
lazy var familyTree = FamilyTree()

因此,如果您想看到"创建家谱!"消息,您需要至少访问该属性一次:

swift 复制代码
ed.familyTree

静态属性和方法

到目前为止,我们创建的所有属性和方法都属于结构体的单独实例,这意味着,如果我们有一个Student结构体,我们可以创建多个学生实例,每个实例都有自己的属性和方法:

swift 复制代码
struct Student {
    var name: String

    init(name: String) {
        self.name = name
    }
}

let ed = Student(name: "Ed")
let taylor = Student(name: "Taylor")

您还可以通过将特定属性和方法声明为静态,要求 Swift 在结构的所有实例之间共享它们。

为了尝试这一点,我们将向Student结构体添加一个静态属性来存储班级中有多少名学生。每次我们创建一个新学生时,我们都会向其中添加一个:

swift 复制代码
struct Student {
    static var classSize = 0
    var name: String

    init(name: String) {
        self.name = name
        Student.classSize += 1
    }
}

因为该classSize属性属于结构本身而不是结构的实例,所以我们需要使用以下方法来读取它

swift 复制代码
Student.classSize:

print(Student.classSize)

访问控制

访问控制可让您限制哪些代码可以使用属性和方法。这很重要,因为您可能希望阻止人们直接读取属性。

我们可以创建一个Person具有id属性的结构来存储他们的社会安全号码:

swift 复制代码
struct Person {
    var id: String

    init(id: String) {
        self.id = id
    }
}

let ed = Person(id: "12345")

一旦创建了该人,我们可以将其设为id私密,这样你就无法从结构外部读取它------尝试写入ed.id根本行不通。

只需使用private关键字,如下所示:

swift 复制代码
struct Person {
    private var id: String

    init(id: String) {
        self.id = id
    }
}

现在只有内部方法Person可以读取该id属性。例如:

swift 复制代码
struct Person {
    private var id: String

    init(id: String) {
        self.id = id
    }

    func identify() -> String {
        return "My social security number is \(id)"
    }
}

另一个常见选项是public,它允许所有其他代码使用该属性或方法。

总结

总结一下:

  • 您可以使用结构创建自己的类型,它们可以具有自己的属性和方法。
  • 您可以使用存储的属性或使用计算属性来动态计算值。
  • 如果您想更改方法内的属性,则必须将其标记为mutating。
  • 初始化器是创建结构体的特殊方法。默认情况下,您会获得成员初始化器,但如果您创建自己的初始化器,则必须为所有属性赋予值。
  • 使用self常量来引用方法内部结构的当前实例。
  • 该lazy关键字告诉 Swift 仅在第一次使用时创建属性。
  • 您可以使用关键字在结构的所有实例之间共享属性和方法static。
  • 访问控制允许您限制哪些代码可以使用属性和方法。
相关推荐
Theodore_10223 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
----云烟----5 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024065 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
开心工作室_kaic5 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it5 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
武子康5 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神6 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
宅小海6 小时前
scala String
大数据·开发语言·scala
qq_327342736 小时前
Java实现离线身份证号码OCR识别
java·开发语言
锅包肉的九珍6 小时前
Scala的Array数组
开发语言·后端·scala