在Swift中,类具有继承性和结构性。同时,类实例存在于堆中,而结构实例存在于堆栈中。
这意味着只允许四种可能中的两种:你可以拥有支持继承的东西,它们存在于堆中,或者你可以拥有不支持继承并且存在于堆栈中的东西。你不能拥有支持继承并且存在于堆栈中的东西,并且你不能拥有不支持继承并且存在于堆中的东西。
这是为什么?是什么让后两种可能性变得不可取?
对于一个安可,为什么结构会获得一个免费的初始化程序,但课程不是?
答案 0 :(得分:2)
这是关于值类型与引用类型的合理设计。
Class
作为引用类型,其继承对应于身份。虽然Struct
作为值类型没有标识,除了它们包含的字段顶部的值,因此可以自由复制。如果您尝试将子字段添加到“继承结构”,则更改该结构的字段或值,并且它们之间不再存在“is-a”关系,如Class
继承,因为说具有较少字段的值类型“is-a”另一个 value-type 是没有意义的。
“继承结构”添加的子字段在复制时可能会被任意丢失(例如,C ++调用时会调用复制构造函数),并使 compatibility 等特性失去意义。另一方面,Class
没有这些问题,因为Class
的每个实例都具有唯一的标识,并且只传递对该实例的引用。
让我们在2D平面上取一个点,这是一个Struct
,包含两个字段:x
和y
。说有另一个子结构代表3D世界的一个点,它有一个子场z
。
当我们喜欢的时候:
point2D = point3D;
然后在作业线上会发生什么?因为point2D
占用的内存已经修复了吗?
从您的问题来看,它直接与堆和堆栈本身的特性相关,当程序进入函数或分配局部变量时,它们被推送到当前堆栈帧(具有固定大小),并且在退出函数后,将进行poped / deallocated,这使得为CPU进行优化变得相对容易。
另一方面,堆具有额外的复杂性,因为程序员能够使用malloc
或free
之类的命令直接与其进行交互 - 从而导致额外的请求和释放时间 - 这会产生更多成本时间它们在初始化时可能需要额外的内存 - 对于开头可能包含或不包含值的字段 - 这会占用更多的空间成本等。将这些特性混淆会使优化变得更加复杂。