gpt4 book ai didi

Swift 枚举通过引用展开

转载 作者:搜寻专家 更新时间:2023-11-01 06:01:51 25 4
gpt4 key购买 nike

我是 Swift 的新手,决定编写自己的 Optional 枚举。

enum MyOptional<Type> {
case none
case some(Type)

func get() -> Type {
switch self {
case .some(let x):
return x
case .none:
fatalError()
}
}
}

var test: MyOptional<String> = MyOptional.some("testString")
test.get().append("#")

但如果我放置一些具有变异函数的结构并调用该函数 - 显然,编译器会告诉我:

error: cannot use mutating member on immutable value: function call returns immutable value test.get().append("#")

Swift 的 Optional 如何通过引用解包返回结构体?

最佳答案

Swift 编译器对Optional 有相当多的内置支持;包括后缀运算符 !? ,它们可以产生左值(驻留在内存中已知位置的值;因此如果表达式是可变的,则允许该内存发生突变).

不幸的是,我不认为可以实现您自己的左值返回运算符(或一般函数),尽管允许您定义 getter 和 setter(例如计算属性和下标)的构造可以被视为 l - 当他们有 setter 时的值:

enum MyOptional<Type> {

case none, some(Type)

var forceUnwrapped: Type {
get {
switch self {
case .some(let x):
return x
case .none:
fatalError()
}
}
set {
self = .some(newValue)
}
}

// just for demonstration; don't actually implement this as a subscript!
subscript() -> Type {
get {
switch self {
case .some(let x):
return x
case .none:
fatalError()
}
}
set {
self = .some(newValue)
}
}
}

var test = MyOptional.some("testString")
test.forceUnwrapped.append("#")
test[].append("#")

在这里,test.forceUnwrappedtest[] 可以被视为左值。当通过它们进行变异时,编译器将通过调用 getter 创建一个临时变量,对该临时变量进行变异,然后使用变异值调用 setter。

尽管在这两种情况下都值得注意,当与赋值一起使用时
(即 test.forceUnwrapped = ... & test[] = ... ), getter 不会被调用;只有 setter,它赋予它们与 Optional 的后缀 ! 略有不同的语义,即使在赋值时,它也会在可选为 nil 时崩溃(即 someOptional! = ...).

作为替代方案,您还可以定义一个方法,该方法采用带有 inout 参数的闭包,允许调用者改变强制展开的值:

enum MyOptional<Type> {

case none
case some(Type)

mutating func forceMutate<R>(_ body: (inout Type) throws -> R) rethrows -> R {
switch self {
case .some(var x):
defer {
self = .some(x)
}
return try body(&x)
case .none:
fatalError()
}
}
}

var test = MyOptional.some("testString")
test.forceMutate { $0.append("#") }

关于Swift 枚举通过引用展开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47577004/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com