我不是SWIFT程序员,所以我对这种语言一无所知.我只是出于好奇才问的. 我遇到了一种语言构造,其中变异函数中的self被赋予一个新值,如下面示例中的函数moveByAssigmentToSelf所示.

struct Point {
    var x = 0.0
    var y = 0.0

    mutating func moveByAssigmentToSelf(_ deltaX: Double, _ deltaY: Double) {
        self = Point(x: x + deltaX, y: y + deltaY)
    }

    mutating func moveByMutatingMembers(_ deltaX: Double, _ deltaY: Double) {
        self.x += deltaX
        self.y += deltaY
    }
}

来自C/C++/Java/C#背景的我认为self是指向内存中(例如堆栈上)某个地方的 struct 值(开始)的指针(地址). 对我来说,在C++ struct 中为应该等同于this的东西赋值看起来非常奇怪.在AFAICT中,函数moveByMutatingMembers应该具有观察上等价的效果,并且将是在C++/Java世界中自然要做的事情.

有人能向非SWIFT程序员解释一下这一概念背后的基本原理/理念是什么吗?

在语言参考(关于表达的章节)中,我能找到的只是以下含糊的陈述:"In an initializer, subscript, or instance method, self refers to the current instance of the type in which it occurs.""In a mutating method of a value type, you can assign a new instance of that value type to self."

我试图理解的是,为什么这个任务是一个好主意,与传统解决方案相比,它解决了哪些编程问题?

换句话说:Why does this make sense from a language-design perspective? Or: What would you lose if you had to do it the C++/Java way?

顺便说一句,出于好奇,我看了一下这个例子中的龙箭disassembly,对于我未经训练的眼睛来说,moveByAssigmentToSelf的输出与替代方案相比看起来效率低得可怕.

推荐答案

来自C/C++/Java/C#背景的我认为自己是一个指针

这是不正确的.因为该类型是值类型( struct ),所以self是该值的副本.mutating的强大之处在于,它将在函数结束时用新值替换先前的值.值没有"实例".它们只是价值观.

有关SWIFT中的值类型的有用介绍,请参阅Value and Reference Types.SWIFT主要文档中的Structures and Enumerations Are Value Types也很有用.

Swift struct 有点像C++,如果你抛switch 于new以及指针和引用的先入为主的概念,把 struct 看作是 struct .它们作为值(副本)传递,就像C++ struct 一样.只是在SWIFT中,这是正常的操作方式,而在C++中,对象通常是通过引用传递的.

对于您提出的关于效率的问题,这只是因为您没有启用优化.With optimizations,它们实际上是相同的代码,并且它们内联到init的调用:

output.Point.moveByAssigmentToSelf(Swift.Double, Swift.Double) -> ():
        movupd  xmm2, xmmword ptr [r13]
        unpcklpd        xmm0, xmm1
        addpd   xmm0, xmm2
        movupd  xmmword ptr [r13], xmm0
        ret

output.Point.moveByMutatingMembers(Swift.Double, Swift.Double) -> ():
        jmp     (output.Point.moveByAssigmentToSelf(Swift.Double, Swift.Double) -> ())

看看你向@Matt提出的问题,我希望这也能帮助你更好地理解这个系统:

var p: Point = Point(x: 1, y: 2) {
    didSet { print("new Point: \(p)")}
}

p.moveByMutatingMembers(1, 2)

这只会打印一次"new Point",因为p只会被替换(设置)一次.

另一方面:

p.x = 0
p.y = 1

这将打印两次"new point",因为p被替换了两次.在Point上调用赋值函数会将整个值替换为新值.

Swift相关问答推荐

{Singleton类}类型的值没有成员$showegView'

在MacOS上检测键盘是否有Globe键

不能将符合协议的SWIFT类的实例分配给需要该协议的Objective-C属性

SwiftUI,如何更改具有多个按钮和一个布尔条件的一个按钮标签

在SwiftUI中使用ForEach循环来显示字典项的键和值在Form视图中

Xcode创建GitHub仓库,但未推送所有文件

除法中如果除以完全因数需要更长时间吗?

避免 `(())` 显式指定 Void 类型的枚举关联值

如何在不将变量转换为字符串的情况下判断变量在 Swift 中是否为 Optional(nil)?

Swiftui 按钮依次显示一组图像

SwiftUI 分段 Select 器的问题

Swift - 订阅视图之外的绑定值

`let case(value)` 和 `case(let value)` 之间的区别 (Swift)

您可以在运行时访问 Picker 元素并更改它们的 colored颜色 吗

如何有条件地格式化 SwiftUI 代码

如何使被拖动的对象成为前景(foreground)对象

仅在 Swift 中创建 Setter

如何使用 Swift/iOS 为人类书写的笔画制作动画?

使用 Swift 在 iOS 8 中为应用程序图标添加徽章

如何判断 firebase 数据库值是否存在?