首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Swift中的类与结构(复制)

Swift中的类与结构(复制)
EN

Stack Overflow用户
提问于 2020-09-15 03:49:19
回答 6查看 806关注 0票数 2

我试图理解为什么结构化和类有不同的结果的概念。为什么这里的结果是相同的,但在结构上却有所不同:

代码语言:javascript
复制
import UIKit

class Message {
    var internalText: String  = "This is some text"
}


// create new instance

var firstMessage = Message()

//if I assign, its a reference to the original instance
var secondMessage = firstMessage

secondMessage.internalText += " with some more text added on."

//print both
print(firstMessage.internalText)
print(secondMessage.internalText)

产出:

这是一些文本添加了一些更多的文本。 这是一些文本添加了一些更多的文本。

现在,如果您将上述声明从"class“更改为"struct”

代码语言:javascript
复制
    struct Message {
        var internalText: String  = "This is some text"
    }
...

产出变成:

这是一些文字 这是一些文本添加了一些更多的文本。

为什么在类声明中它会更改firstMessage对象。他们是同一个对象吗?如果我从旧对象分配一个新对象,这是一条规则吗?然后,我必须声明secondMessage = Message(),以使它成为一个新实例。提前谢谢。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2020-09-15 05:16:08

为什么在类声明中它会更改firstMessage对象。他们是同一个对象吗?

您给出的示例非常好,因为它简洁地说明了classstruct之间的区别,并且您得到了一个非常接近的-> <- -回答了您自己的问题,即使您没有意识到它。正如其他答案所解释的,class创建了一个引用类型,这意味着当您将类的实例分配给变量时,该变量将获得对对象的引用,而不是它的副本。你自己也这么说:

代码语言:javascript
复制
//if I assign, its a reference to the original instance
var secondMessage = firstMessage

在您的示例中,firstMessagesecondMessage实际上是对您创建的一个对象的引用。这类事情总是在面向对象的语言中完成的,因为知道您正在处理的是一个特定的对象,而不是一个副本,这一点很重要,特别是如果您想对该对象进行更改的话。但这也带来了危险:如果您的代码可以获得对对象的引用并对其进行更改,那么程序中的其他代码也是如此。当您开始编写多线程代码时,可以更改的共享对象会造成各种麻烦。当您向secondMessage添加文本时,firstMessage也会更改,因为两个变量都引用同一个对象。

Message的声明更改为struct使其成为一种值类型,其中赋值(例如)将创建所涉对象的新副本,而不是对同一对象的新引用。当您在将secondMessage更改为struct后向struct添加文本时,赋值secondMessage = firstMessage创建了firstMessage的副本,并且只更改了该副本。

如果我从旧对象分配一个新对象,这是一条规则吗?

您的赋值是创建对象的副本还是引用,正如您已经展示的那样,取决于所分配的对象是否具有引用语义(class)或值语义(struct)。所以你需要意识到不同之处,但大多数时候你不需要太认真地思考。如果您处理的对象不关心对象的标识,并且主要关注对象的内容(如数字、字符串或数组),那么请将其看作是一个struct。如果您关心要处理的对象(如前窗口或当前文档),那么这将是一个class

然后,我必须声明secondMessage = Message(),以使它成为一个新实例。

正确--如果Message是一个类,将一个分配给一个新变量或将其传递给一个方法不会创建一个新的变量。因此,您是否更有可能关心您正在处理的消息,或者消息中的内容?

票数 2
EN

Stack Overflow用户

发布于 2020-09-15 04:04:22

在Swift中,类是引用类型,而结构是值类型。值类型是在变量赋值时复制的,而引用类型则不是。

更多解释

系统将实例化的类和结构存储到内存中。存储数据涉及内存的两个主要部分,堆栈和堆。堆栈包含当前方法或函数中引入的局部变量,堆用作某种外部内存,存储更大的值。程序只能访问存储在堆栈中的变量,因此应该在堆栈中保存对堆中值的引用。

当您使用类似于Message()的东西实例化类对象时,内存的堆中保留了一个空闲空间,并在堆栈中保留了对它的引用。当您将相同的变量分配给新的变量时,引用将被复制,两个变量将引用堆中相同的字节,因此更改一个也会改变另一个。

当使用structs时,所有的空间都保留在堆栈上,并且没有指针或引用之类的东西,所以当分配给一个新变量时,所有数据都会被复制(实际上,系统足够聪明,只复制正在更改的必要值)。

你可以看到一个很好的教程涵盖这些主题这里

票数 3
EN

Stack Overflow用户

发布于 2020-09-15 04:00:36

让我们用一个例子来理解同样的概念,假设您有一个google表,其中您正在添加一些文本,并且每次您将该页共享给其他人以编辑或删除目的。因此,当另一个人做任何改变,你可以看到一次。这个概念在课堂上被遵循。此外,类是引用类型,因为这里传递引用(工作表)。

但是,您已经下载了该谷歌工作表,并将其副本发送给另一个人,因此在此期间,您无法看到更改,除非该人将该页发回。这是相同的概念在结构中遵循。结构是值类型,因为我们正在传递副本(下载的工作表)。

We can inherit class but cannot inherit struct

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63894783

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档