相同点:
1.定义属性用于存储值 (property
)
2.定义方法用于提供功能 (function
)
3.定义下标操作使得可以通过下标语法来访问实例所包含的值 (subscript
)
4.定义构造器用于生成初始化值 (initializers
)
5.通过扩展以增加默认实现的功能 (extension
)
6.实现协议以提供某种标准功能 (protocol
)
不同点:
1.class是引用类型;struct是值类型
2.class支持继承;struct不支持继承
3.class声明的方法修改属性时不需要mutating
关键字;struct需要
4.class中每一个成员变量都必须被初始化,否则编译器会报错,而struct
不需要,编译器会自动帮我们生成init函数
,给变量赋一个默认值
5.class支持引用计数(reference counting)(允许对一个类的多次引用),struct不支持
6.class支持type casting(类型转换)(允许在运行时检查和解释一个类实例的类型),struct不支持
7.class支持deinitializers(析构器)(允许一个类实例释放任何其所被分配的资源),struct不支持
8.变量赋值方式不同(深浅copy),class浅拷贝,struct深拷贝,class的赋值是传递引用,struct则是copy传值,不是使用引用计数。
9.内存管理:struct存储在stack中,class存储在heap中、
10.方法派发方式:struct的方法调用是静态绑定
,而class的方法调用是动态实现
Tip: class的对象是引用类型,而struct是值类型。所以class的赋值是传递引用,则是copy传值,不是使用引用计数。
class为了支持的额外功能则会增加其复杂性。一般,更倾向使用选择struct和enum,因为他们更容易理解,而class,则在合适和必要的时候使用。实际上,这意味着大多数的自定义数据类型定义为struct和enum就可以
了。
class和struct的选择
struct实例总是通过值传递,class实例总是通过引用传递。这意味两者适用不同的任务。当你在考虑一个工程项目的数据结构和功能的时候,你需要决定每个数据结构是定义成struct还是class。
按照通用的准则,当符合一条或多条以下条件时,请考虑构建struct
:
- 该数据结构的主要目的是用来封装少量相关简单数据值。
- 有理由预计该数据结构的实例在被赋值或传递时,封装的数据将会被拷贝而不是被引用。
- 该数据结构中储存的值类型属性,也应该被拷贝,而不是被引用。
- 该数据结构不需要去继承另一个既有类型的属性或者行为。
- 使用struct和protocol来实现model继承和共享行为,如下代码所示:
protocol AnimalCommonProtocol {
var name: String? { get set }
var weight: Double { get set }
func run()
}
struct Cat : AnimalCommonProtocol {
func run() {
print("cat run")
}
var name: String?
var weight: Double
var gender: String?
}
struct Dog : AnimalCommonProtocol {
func run() {
print("dog run")
}
var name: String?
var weight: Double
var type: String?
}
总结起来就是一句话:能使用struct就不要使用class
为什么优选struct:
- 使用struct不需要考虑内存泄漏和多线程读写的问题,因为在传递值的时候它会进行值的copy
- struct存储在stack中,class存储在heap中,struct更快
- 在运行时,struct在性能方面更优于class,原因是struct的方法调用是静态绑定,而class的方法调用是动态实现的。这就是尽可能得使用struct代替class的又一个好的原因。
恒等运算符
因为class是引用类型,有可能有多个常量和变量在幕后同时引用同一个类实例。(对于struct和enum来说,这并不成立。因为它们作为值类型,在被赋予到常量、变量或者传递到函数时,其值总是会被拷贝。)
如果能够判定两个常量或者变量是否引用同一个类实例将会很有帮助。为了达到这个目的,Swift 内建了两个恒等运算符:
- 等价于(===)
- 不等价于(!==)
运用这两个运算符检测两个常量或者变量是否引用同一个实例:
if tenEighty === alsoTenEighty {
print("tenEighty and alsoTenEighty refer to the same Resolution instance.")
}
//打印 "tenEighty and alsoTenEighty refer to the same Resolution instance."
注意,
等价于
(用三个=
表示)与等于
(用两个=
表示)不同:
1.等价于
表示两个类类型(class type)
的常量或者变量引用同一个类实例。
2.等于
表示两个实例的值相等
或相同
,判定时要遵照设计者定义的评判标准,因此相对于相等
来说,这是一种更加合适的叫法。
网友评论