Swift 和可变结构 [英] Swift and mutating struct

查看:34
本文介绍了Swift 和可变结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当谈到在 Swift 中改变值类型时,我并不完全理解.

There is something that I don't entirely understand when it comes to mutating value types in Swift.

正如The Swift Programming Language"iBook 所述:默认情况下,值类型的属性不能从其实例方法中修改.

As the "The Swift Programming Language" iBook states: By default, the properties of a value type cannot be modified from within its instance methods.

因此,为了实现这一点,我们可以在结构体和枚举中使用 mutating 关键字声明方法.

And so to make this possible we can declare methods with the mutating keyword inside structs and enums.

我不完全清楚的是:您可以从结构外部更改 var,但不能从其自己的方法更改它.这对我来说似乎违反直觉,就像在面向对象的语言中一样,您通常会尝试封装变量,以便只能从内部更改它们.对于结构,这似乎是相反的.为了详细说明,这是一个代码片段:

The thing that is not entirely clear to me is this: You can change a var from outside a struct, but you cannot change it from its own methods. This seems counter-intuitive to me, as in Object Oriented languages, you generally try to encapsulate variables so they can only be changed from within. With structs this appears to be the other way around. To elaborate, here's a code snippet:

struct Point {
    var x = 0, y = 0
    mutating func moveToX(x: Int, andY y:Int) { //Needs to be a mutating method in order to work
        self.x = x
        self.y = y
    }
}

var p = Point(x: 1, y: 2)
p.x = 3 //Works from outside the struct!
p.moveToX(5, andY: 5) 

有谁知道为什么结构不能从它们自己的上下文中改变它们的内容,而在其他地方可以很容易地改变内容?

Does anyone know the reason why structs cannot change their content from inside their own context, while the contents can easily be changed elsewhere?

推荐答案

可变性属性标记在存储(常量或变量)上,而不是类型上.你可以认为 struct 有两种模式:mutableimmutable.如果您将结构值分配给不可变存储(我们在 Swift 中称其为 letconstant),则该值将变为不可变模式,并且您无法更改该值中的任何状态.(包括调用任何变异方法)

The mutability attribute is marked on a storage (constant or variable), not a type. You can think struct has two modes: mutable and immutable. If you assign a struct value to an immutable storage (we call it let or constant in Swift) the value becomes immutable mode, and you cannot change any state in the value. (including calling any mutating method)

如果将值分配给可变存储(我们称之为 varvariable 在 Swift 中),您可以自由修改它们的状态,并调用允许使用变异方法.

If the value is assigned to a mutable storage (we call it var or variable in Swift), you're free to modify the state of them, and calling of mutating method is allowed.

此外,类没有这种不可变/可变模式.IMO,这是因为类通常用于表示可引用实体.可引用实体通常是可变的,因为很难以不可变的方式以适当的性能创建和管理实体的引用图.他们以后可能会添加此功能,但至少现在不会.

In addition, classes don't have this immutable/mutable mode. IMO, this is because classes are usually used to represent reference-able entity. And reference-able entity is usually mutable because it's very hard to make and manage reference graphs of entities in immutable manner with proper performance. They may add this feature later, but not now at least.

对于Objective-C 程序员来说,可变/不可变的概念非常熟悉.在 Objective-C 中,我们为每个概念设置了两个独立的类,但在 Swift 中,您可以使用一个结构体来实现这一点.工作一半.

For Objective-C programmers, mutable/immutable concepts are very familiar. In Objective-C we had two separated classes for each concept, but in Swift, you can do this with one struct. Half work.

对于 C/C++ 程序员来说,这也是非常熟悉的概念.这正是 const 关键字在 C/C++ 中所做的.

For C/C++ programmers, this is also very familiar concept. This is exactly what const keyword do in C/C++.

另外,不可变值可以很好地优化.理论上,Swift 编译器(或 LLVM)可以对 let 传递的值执行复制省略,就像在 C++ 中一样.如果您明智地使用不可变结构,它将胜过引用计数的类.

Also, immutable value can be very nicely optimised. In theory, Swift compiler (or LLVM) can perform copy-elision on values passed by let, just like in C++. If you use immutable struct wisely, it will outperform refcounted classes.

正如@Joseph 声称这并没有提供为什么,我添加了一点.

As @Joseph claimed this doesn't provide why, I am adding a little more.

结构有两种方法.普通变异方法.Plain 方法意味着不可变(或非可变).这种分离只是为了支持不可变语义.处于不可变模式的对象根本不应改变其状态.

Structs have two kind of methods. plain and mutating methods. Plain method implies immutable (or non-mutating). This separation exists only to support immutable semantics. An object in immutable mode shouldn't change its state at all.

那么,不可变方法必须保证这种语义不变性.这意味着它不应该改变任何内部值.因此,编译器不允许在不可变方法中对自身进行任何状态更改.相比之下,变异方法可以自由修改状态.

Then, immutable methods must guarantee this semantic immutability. Which means it shouldn't change any internal value. So compiler disallows any state changes of itself in a immutable method. In contrast, mutating methods are free to modify states.

然后,你可能会有一个问题,为什么默认是不可变的?那是因为很难预测变异值的未来状态,而这通常成为头痛和错误的主要来源.许多人一致认为解决方案是避免可变内容,然后 默认情况下不可变几十年来一直是 C/C++ 家族语言及其派生的愿望清单.

And then, you may have a question of why immutable is the default? That's because it's very hard to predict the future state of mutating values, and that usually becomes the main source of headaches and bugs. Many people agreed that the solution is avoiding mutable stuffs, and then immutable by default was on top of wish list for decades in C/C++ family languages and its derivations.

查看纯函数式风格了解更多详情.无论如何,我们仍然需要可变的东西,因为不可变的东西有一些弱点,讨论它们似乎是题外话.

See purely functional style for more details. Anyway, we still need mutable stuffs because immutable stuffs have some weaknesses, and discussing about them seems to be out of topic.

我希望这会有所帮助.

这篇关于Swift 和可变结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆