Swift Classstruct
Posted 博BOBO
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift Classstruct相关的知识,希望对你有一定的参考价值。
1.定义
在Swift标准库中,绝大多数的公开类型都是结构体,而枚举和类只占很小一部分
比如Bool、Int、Double、 String、 Array、Dictionary等常见类型都是结构体所有的结构体都有一个编译器自动生成的初始化器( initializer ,初始化方法、构造器、构造方法)
SwiftObject
在swift中,如果没有明确声明父类的类,则会隐式地继承自 SwiftObject (支持与 Objective-C 混编的前提下,因为 SwiftObject 是一个 Objective-C 类),隐式继承来源于 swift 的 ABI/TypeLayout.rst 文档。
SwiftObject 的声明是
SWIFT_OBJC_INTEROP
为true
的情况下才有声明的,而在苹果平台下,都是支持 swift 与 Objective-C 进行混编的,因此SWIFT_OBJC_INTEROP
为1(true)
,SWIFT_OBJC_INTEROP
宏的定义可在 Config.h 中找到从 SwiftObject 的定义中可以看到
- 第一个成员变量和 Objective-C 一样是
isa
指针,暂时猜想和 Objective-C 中的isa
指针功能一样- 第二个成员变量是一个
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS
宏,其定义可在 HeapObject.h 和 RefCount.h中找到,从命名上看是引用计数器
2.区别
2.1.类是引用类型,结构体是值类型。
值类型在传递和赋值时将进行复制,而引用类型则只会使用引用对象的一个指向。引用类型是在堆上,而值类型是在栈上进行存储和操作。相比栈上的操作,对上的操作更加复杂耗时,所以苹果官方推荐使用结构体,这样可以提高App运行的效率。值类型赋值给let var 或者函数传参的时候全是深拷贝;引用类型赋值给let var 或者函数传参的时候完,是将内存地址拷贝一份,属于浅拷贝。结构体属于值类型,标准库中的结构体采用copy on write策略,优化效率;
2.2.class有这几个功能struct没有的:
class可以继承,这样子类可以使用父类的特性和方法。
类型转换可以在runtime的时候检查和解释一个实例的类型。
可以用deinit来释放资源。
一个类可以被多次引用。
2.3.结构体不可以继承,可以继承;
2.4.结构体初始化的时候必须要给属性赋值,来决定结构体在内存中的布局.Class初始化的时候可以暂时不用赋值;
2.5.都可以实现方法,都可以添加计算属性和存储属性,都支持属性监听,都支持扩展.都可以遵守协议;
2.6.required关键字只支持Class, Class可以用static和Class 关键字修饰静态方法;Struct 只能用Static 修饰;
2.7,类一定是分配在堆空间上,结构体可能分配在堆空间:比如类中的结构体属性,栈空间:比如声明在方法中,数据段:声明为全局变量
2.8类,有析构函数。结构体不能有析构函数。
2.9.结构体构造函数会自动生成带参数的构造器。类不会对有初始化赋值生成带参数的构造器。
2.10.类有继承特性,结构体没有继承特性。结构体无继承特性,则无法对成员属性、成员方法、类属性、类方法进行重载。结构体的函数操作符需要static,不能使用class。
2.11.类中的每一个成员变量都必须被初始化,否则编译器会报错。而结构体不需要,编译器会自动帮我们生成init函数,给变量赋一个默认值。
2.12.类中可以有单例,结构体不能有
2.13NSUserDefaults:结构体不能序列化成NSDate,无法归档。类可以
2.14.混合开发时,oc中不能调用swift中的结构体
2.15.方法派发:
• 静态派发:编译器讲函数地址直接编码在汇编中,调用的时候根据地址直接跳转到实现,编译器可以进行内联等优化,Struct都是静态派发。
•动态派发:运行时查找函数表,找到后再跳转到实现,动态派发仅仅多一个查表环节并不是他慢的原因,真正的原因是它阻止了编译器可以进行的内联等优化手段
2.16.struct在func里面需要修改property的时候需要加上mutating关键字,而class就不用。
3.相同点
3.1定义存储值的属性
3.2定义方法
3.3定义下标以使用下标语法提供对其值的访问
3.4定义初始化器
3.5使用 extension 来拓展功能
3.6遵循协议来提供某种功能
3.7.范型
3.8协议采纳
4.观察器
4.结构体的内存结构
struct Point
var x: Int = 0
var y: Int = 0
print(MemoryLayout<Point>.size) // 16
print(MemoryLayout<Point>.stride) // 16
print(MemoryLayout<Point>.alignment) // 8
通过打印可知结构体Point实际占用16字节,总占用16字节,内存对齐为8字节。
这很好理解,因为两个存储属性x和y都是Int类型,都是占用8字节,所以实际占用16字节。
struct Point
var x: Int = 0
var y: Int = 0
var b: Bool = true
print(MemoryLayout<Point>.size) // 17
print(MemoryLayout<Point>.stride) // 24
print(MemoryLayout<Point>.alignment) // 8
这里Point实际占用17字节,因为存储属性x是Int型占用8字节,y是Int型占用8字节,b是Bool型占用1字节。
内存对齐为8字节,所以总占用是8+8+8=24字节。
5.如何选择
5.1、 堆栈的空间有限,对于大量的逻辑的对象,创建类要比创建结构好一些。
5.2、 结构表示如点、矩形和颜色这样的轻量对象,例如,如果声明一个含有 1000 个点对象的数组,则将为引用每个对象分配附加的内存。在此情况下,结构的成本较低。
5.3、 在表现抽象和多级别的对象层次时,类是最好的选择。
5.4、 大多数情况下该类型只是一些数据时,结构时最佳的选择。
5.5、结构体的主要目的是为了封装一些相关的简单数据值。
5.6、当你在赋予或者传递结构实例时,有理由需要封装的数据值被拷贝而不是引用。
5.7、任何存储在结构体中的属性是值类型,也将被拷贝而不是被引用。
5.8、结构体不需要从一个已存在类型继承属性或者行为。
以上是关于Swift Classstruct的主要内容,如果未能解决你的问题,请参考以下文章