28 如何为类、结构体以及枚举添加属性

简介: 如何为类、结构体以及枚举添加属性

如何为类、结构体以及枚举添加属性

存储属性

  • 在其最简单的形势下,存储属性是一个作为特定类和结构体实例一部分的常量或变量。存储属性要么是变量存储属性(由var关键字引入)要么是常量存储属性(由let 关键字引入)

常量结构体实例的存储属性

  • 如果你创建了一个结构体的实例并且把这个实例赋给常量,你不能修改这个实例的属性,即使是声明为变量的属性

延迟存储属性

  • 延迟存储属性的初始值在其第一次使用时才进行计算。你可以通过在其声明前标注lazy修饰语来表示一个延迟存储属性
  • 如果被标记为lazy修饰符的属性同时被多个线程访问并且属性还没有被初始化,则无法保证属性只初始化一次。

image.png

计算属性

  • 除了存储属性,类、结构体和枚举也能够定义计算属性,而它实际并不存储值。相反,它提供一个读取器和一个可选的设置器来间接得到和设置其他的属性和值

image.png

简写setter

  • 如果一个计算属性的设置器没有为将要被设置的值定义一个名字,那么它将被默认命名为newValue

image.png

简写getter

  • 如果整个getter的函数体是一个单一的表达式,那么getter隐式返回这个表达式

image.png

只读计算属性

  • 一个有读取器但是没有设置器的计算属性就是所谓的只读计算属性。只读计算属性返回一个值,也可以通过点语法访问,但是不能被修改为另一个值
  • 你必须用var关键字定义计算属性(包括只读计算属性)为变量属性,因为它们的值不是固定的。let关键字只用于常量属性,用于明确那些值一旦作为实例初始化就不能更改

image.png

属性观察者

  • willSet会在该值被存储之前被调用
  • didSet会在一个新值被存储后被调用
  • 如果你实现了一个willSet观察者,新的属性会以常量形式参数传递。你可以在你的willSet实现中为这个参数定义名字。如果你没有为它命名,那么它会使用默认的名字newValue
  • 如果你实现了一个didSet观察者,一个包含旧属性值得常量形式参数将会被传递。你可以为它命名,也可以使用默认的形式参数名oldValue。如果你在属性自己的didSet观察者里给自己赋值,你赋值的新值就会取代刚刚设置的值

image.png

全局和局部变量

  • 计算属性和观察属性的能力同样对全局变量和局部变量有效。全局变量时定义在任何函数、方法、闭包或者类型环境之外的变量。局部变量是定义在函数、方法或者闭包环境之中的变量


image.png

类型属性

  • 使用static关键字来定义类型属性。对于类类型的计算类型属性,你可以使用class关键字来允许子类重写父类的实现

image.png

如何为类、结构体以及枚举添加方法

实例方法

  • 实例方法是属于特定类实例、结构体实例或者枚举实例的函数。它们为这些实例提供功能性,要么通过提供访问和修改实例属性的方法,要么通过提供与实例目的相关的功能

image.png

实例方法-self

  • 每一个类的实例都隐含一个叫做self的属性,它完完全全与实例本身相等。你可以使用self属性来在当前实例当中调用它自身的方法
  • 实际上,你不需要经常在代码中写self。如果你没有显式地写出self,Swift会在你于方法中使用已知属性或者方法的时候假定你是调用了当前实例中的属性或者方法
  • 例外就是当一个实例方法的形式参数名与实例中某个属性拥有相同的名字的时候。在这种情况下,形式参数名具有优先权,并且调用属性的时候使用更加严谨的方式就很有必要了。你可以使用self属性来区分形式参数和属性名

image.png

在实例方法中修改属性

  • 结构体和枚举是值类型。默认情况下,值类型属性不能被自身的实例方法修改
  • 你可以选择在func关键字前放一个mutating关键字来指定方可以修改属性


image.png

在mutating方法中赋值给self

  • Mutating方法可以指定整个实例给隐含的self属性

image.png

枚举的mutating方法

  • 枚举的异变方法可以设置隐含的self属性为相同枚举里的不同成员


image.png

类型方法

  • 通过在func关键字之前使用static关键字来明确一个类型方法。类同样可以使用class关键字来允许子类重写父类对类型方法的实现

image.png

像访问数组和字典一样访问类和结构体:下标和下标重载

下标

  • 类、结构体和枚举可以定义下标,他可以作为访问集合、列表或序列成员元素的快捷方式。你可以使用下标通过索引值来设置或检索值而不需要为设置和检索分别使用实例方法
  • 你可以为一个类型定义多个下标,并且下标会基于传入的索引值的类型选择合适的下标重载使用。下标没有限制单个维度,你可以使用多个输入形参来定义下标以满足自定义类型的需求


下标语法

  • 下标脚本允许你通过在实例名后面的方括号内写一个或多个值对该类的实例进行查询。它的语法类似于实例方法和计算属性。使用关键字subscript来定义下标,并且指定一个或多个输入形式参数和返回类型,与实例方法一样。与实例方法不同的是,下标可以是读写也可以是只读的

image.png

下标参数

  • 下标可以接受任意数量的输入形式参数,并且这些输入形式参数可以是任意类型。下标也可以返回任意类型。下标可以使用变量形式参数和可变形式参数,但是不能使用输入输出形式参数或提供默认形式参数值

image.png

image.png

类型下标

  • 实例下标,如果上文描述的那样,你在对应类型的实例上调用下标。你同样也可以定义类型本身的下标。这类下标叫做类型下标。你可以通过在subscript关键字前加static关键字来标记类型下标。在类里则使用class关键字,这样可以允许子类重写父类的下标实现

image.png








目录
相关文章
|
2月前
|
安全 C# 索引
C#一分钟浅谈:属性与索引器的定义
本文深入浅出地介绍了C#编程中的属性和索引器。属性让字段更安全,通过访问器方法在读写时执行额外操作,如验证数据有效性;索引器则赋予类数组般的访问方式,支持基于索引的数据访问模式。文章通过示例代码展示了如何定义及使用这两种特性,并提供了常见问题及其解决方案,帮助读者写出更健壮、易维护的代码。希望读者能从中学习到如何有效利用属性和索引器增强C#类的功能性。
83 12
|
5月前
|
编译器 C++
【C++】类和对象③(类的默认成员函数:赋值运算符重载)
在C++中,运算符重载允许为用户定义的类型扩展运算符功能,但不能创建新运算符如`operator@`。重载的运算符必须至少有一个类类型参数,且不能改变内置类型运算符的含义。`.*::sizeof?`不可重载。赋值运算符`=`通常作为成员函数重载,确保封装性,如`Date`类的`operator==`。赋值运算符应返回引用并检查自我赋值。当未显式重载时,编译器提供默认实现,但这可能不足以处理资源管理。拷贝构造和赋值运算符在对象复制中有不同用途,需根据类需求定制实现。正确实现它们对避免数据错误和内存问题至关重要。接下来将探讨更多操作符重载和默认成员函数。
|
Java
属性与this关键字
属性与this关键字
50 0
|
6月前
|
C++
【C++】结构体、类和引用
【C++】结构体、类和引用
48 0
|
C语言 C++
自定义类型枚举(下)
自定义类型枚举
35 0
自定义类型枚举(上)
自定义类型枚举
32 0
|
存储 Swift
13 如何为类和结构体自定义运算符实现
如何为类和结构体自定义运算符实现
67 0
|
Java 编译器 C++
常量接口 vs 常量类 vs 枚举区别
把常量定义在接口里与类里都能通过编译,那2者到底有什么区别呢?
69 0
|
存储 编译器 C++
类的默认成员函数、赋值运算符重载(二)
如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。
60 0