如何将类对象传递给函数但防止突变?

  • 本文关键字:函数 突变 对象 swift
  • 更新时间 :
  • 英文 :


我看不出 Swift 语言中的哪个位置可以将类对象传递给函数,但通过调用将隐式改变对象的函数或设置公共变量来防止该函数改变对象。我正在收集这个设施根本不存在,任何人都可以确认吗?

也就是说,所有物体在可见的任何地方总是可变的。

这在整个可可中非常普遍。创建一个不可变类和一个可变子类。有关示例,请参阅 AVComposition/AVMutableComposition、CBService/CBMutableService、CNContact/CNMutableContact。

在 ObjC 中,这也是集合(数组、字典等)的常见做法,但由于这些是 Swift 中的值类型,因此无需使用这些类(NSArray/NSMutableArray)。

在 Swift 中,你不创建两个类,而是创建一个不可变的协议和一个类:

protocol Person: AnyObject {
var name: String { get }
var address: String { get }
}
class MutablePerson: Person {
var name: String = ""
var address: String = ""
}

现在,任何接受Person的函数都将有一个不可变的对象,任何接受MutablePerson的函数都将能够改变它。这是一种常规模式,可用于让程序的不同部分访问对象 API 的不同切片。它比const更通用、更灵活。

也就是说,这在 Swift 中并不像在 ObjC 中那样常见,因为在大多数情况下,如果这很有用,那么类型无论如何都应该是一个结构体。但如果需要,它是绝对可用的。


对于您关于使用两个类执行此操作的问题,就像在 ObjC 中一样,只要在同一文件中定义这两个类,这是可能的。只是有点乏味:

public class Person {
public fileprivate(set) var name: String = ""
public fileprivate(set) var address: String = ""
}
public class MutablePerson: Person {
public override var name: String {
get { super.name }
set { super.name = newValue }
}
public override var address: String {
get { super.address }
set { super.address = newValue }
}
}

属性包装器可能会改善这一点,但我一直无法弄清楚如何。

我想不出允许使用方法的方法,但属性没有问题**。只需使用Immutable作为函数参数。

final class Class {
var property = true
}
var object = Immutable(Class())
object.property = false // Cannot assign to property: 'object' is immutable
/// An affordance for accessing the properties of an object
/// without the ability to mutate them.
@dynamicMemberLookup
public struct Immutable<Object: AnyObject> {
private let object: Object
}
// MARK: - public
public extension Immutable {
init(_ object: Object) {
self.object = object
}
subscript<Value>(dynamicMember keyPath: KeyPath<Object, Value>) -> Value {
object[keyPath: keyPath]
}
}

**getters可能会发生变异,并且它们可能会返回突变闭包。 但这也是协议方法的一个问题。我们现在能做的最好的事情就是一个普遍准确的黑客。

您要查找的是值类型(例如structs)。如果更改值类型的任何属性,则会更改实例本身。

这意味着,当您将值类型传递给函数时,该函数将无法改变所述值类型的任何属性。

另一方面,classes 是引用类型,因此更改它们的任何属性都不会更改类实例本身。因此,您不能禁止函数修改类的可变属性(除非您将它们设置为私有的所述属性的 setter)。

最新更新