Swift中是否有类似JavaScript的数组冻结机制?何为数组冻结?
好问题!先明确下你说的「数组冻结」是什么,再聊聊Swift里的对应方案:
数组冻结的定义
你提到的「数组冻结」指的是将一个已填充好元素的数组转为完全不可变状态:冻结后无法对数组执行添加、删除元素的操作,也不能修改现有元素的值。就像你给出的JavaScript示例那样:
/* This is javascript code */ var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.push("Kiwi"); // 先向数组添加元素 // 执行冻结,之后数组无法被修改 Object.freeze(fruits);
冻结后的数组,任何尝试修改它的操作(比如push、splice或者直接修改索引值)都会被阻止(在严格模式下会抛出错误)。
Swift中的对应实现方案
Swift里没有直接和Object.freeze()完全同名的方法,但有两种常用方式实现类似的“冻结”效果:
1. 使用let声明不可变数组
Swift的数组本身区分**可变(var声明)和不可变(let声明)**两种状态。你可以先使用var创建数组并添加元素,之后将它赋值给一个let常量,这样这个常量数组就无法被修改了:
// 先创建可变数组并添加元素 var mutableFruits = ["Banana", "Orange", "Apple", "Mango"] mutableFruits.append("Kiwi") // 将可变数组转为不可变(冻结)状态 let frozenFruits = mutableFruits // 以下操作都会编译报错: // frozenFruits.append("Grape") // 无法添加元素 // frozenFruits.remove(at: 0) // 无法删除元素 // frozenFruits[0] = "Pear" // 无法修改元素
⚠️ 注意:和JS的Object.freeze()一样,这是浅不可变。如果数组中的元素是引用类型(比如自定义的class实例),let只能保证数组的结构(元素个数、顺序)不能变,但元素内部的属性仍然可以修改。比如:
class Fruit { var name: String init(name: String) { self.name = name } } var mutableFruits = [Fruit(name: "Banana")] let frozenFruits = mutableFruits // 仍然可以修改元素内部的属性 frozenFruits[0].name = "Blueberry"
2. 实现深冻结(可选)
如果需要连元素内部也完全不可变,你可以:
- 使用值类型(比如
struct而不是class)来定义元素,因为值类型的实例在let声明下所有属性都是不可变的; - 或者自定义一个只读的封装结构体,对外只提供数组的只读访问方法,完全隐藏修改的入口。
比如用值类型的例子:
struct Fruit { let name: String init(name: String) { self.name = name } } var mutableFruits = [Fruit(name: "Banana")] mutableFruits.append(Fruit(name: "Kiwi")) let frozenFruits = mutableFruits // 此时不仅数组结构不能改,元素内部的属性也无法修改 // frozenFruits[0].name = "Pear" // 编译报错
内容的提问来源于stack exchange,提问作者Faruk Hossain
相关产品推荐
相关产品推荐

