0Pricing
Swift Academy · 课时

非变更式替代方案

返回新值,而不是原地修改。

非变更式替代方案 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。

返回值而不是直接变更

非变更方法不会直接更改实例,而是返回一个已经应用更改的全新值。

struct Counter {
    var value: Int
    func incremented() -> Counter {
        return Counter(value: value + 1)
    }
}
let c = Counter(value: 0)
let next = c.incremented()
print(c.value, next.value)

原值保持不变

由于没有进行任何变更,原值会被保留,同时生成一个新值。

struct Vector {
    var x: Int
    var y: Int
    func scaled(by factor: Int) -> Vector {
        return Vector(x: x * factor, y: y * factor)
    }
}
let v = Vector(x: 2, y: 3)
let big = v.scaled(by: 10)
print(v.x, v.y, big.x, big.y)

可用于常量实例

非变更方法不会更改接收调用的实例,因此可以在 let 常量上调用。

struct Money {
    var cents: Int
    func plus(_ other: Int) -> Money {
        return Money(cents: cents + other)
    }
}
let m = Money(cents: 100)
print(m.plus(50).cents)

命名约定

Swift 的约定是:变更方法使用祈使动词(sort),非变更方法使用过去分词或 -ed/-ing 形式(sorted)。

var nums = [3, 1, 2]
let ordered = nums.sorted()
nums.sort()
print(ordered, nums)

sorted 与 sort

标准库遵循这一约定:sorted() 返回一个新数组,而 sort() 会直接变更原数组。

let a = [5, 2, 8, 1]
let b = a.sorted()
print(a)
print(b)

reversed 与反向操作

同样,reversed() 不会进行变更。这里使用 Array 将结果具体化。

let a = [1, 2, 3]
let b = Array(a.reversed())
print(a, b)

串联非变更调用

非变更方法会返回值,因此您可以流畅地串联调用它们。

let result = [4, 2, 9, 1].sorted().map { $0 * 2 }
print(result)

函数式风格

返回新值而不是直接变更,支持一种易于测试和推理的函数式风格。

struct Account {
    var balance: Int
    func deposited(_ n: Int) -> Account {
        return Account(balance: balance + n)
    }
}
let a0 = Account(balance: 0)
let a1 = a0.deposited(100).deposited(50)
print(a0.balance, a1.balance)

避免共享状态错误

生成新值可以避免意外的共享变更,这一点在线程之间尤其有价值。

struct Settings {
    var volume: Int
    func with(volume newVolume: Int) -> Settings {
        return Settings(volume: newVolume)
    }
}
let base = Settings(volume: 5)
let loud = base.with(volume: 11)
print(base.volume, loud.volume)

何时应改为直接变更

如果您在循环中反复更新同一个实例,直接变更通常比创建许多副本更高效。

var total = 0
for n in 1...5 {
    total += n
}
print(total)

同时提供两种形式

设计良好的类型有时会像标准库一样同时提供两种形式,让调用者选择直接变更或生成新值。

struct Text {
    var value: String
    func uppercased() -> Text {
        return Text(value: value.uppercased())
    }
    mutating func uppercase() {
        value = value.uppercased()
    }
}
var t = Text(value: "hi")
let u = t.uppercased()
t.uppercase()
print(u.value, t.value)

快速检查

测试非变更设计。

回顾

作为直接变更的替代方案,非变更方法会返回一个已应用更改的新值,保留原值不变,并且可以用于 let 实例。Swift 的约定是将祈使名称(sort)与 -ed/-ing 名称(sorted)配对。

let a = [3, 1, 2]
let b = a.sorted()
print(a, b)

常见问题解答

「非变更式替代方案」课时是免费的吗?

是的 — 「非变更式替代方案」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。

「非变更式替代方案」这节课中我会学到什么?

返回新值,而不是原地修改。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Swift Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「非变更式替代方案」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Swift Academy 课中编写并运行代码吗?

能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 值类型与不可变性
  2. mutating 关键字
  3. mutating 与 self 重新赋值
  4. 非变更式替代方案
← 返回 Swift Academy