玩Swift,来自Java背景,为什么要选择Struct而不是Class?看起来它们是一样的东西,只不过Struct提供的功能更少。那为什么选择它呢?


当前回答

结构是值类型,类是引用类型

值类型比引用类型快 值类型实例在多线程环境中是安全的 多线程可以改变实例,而不必担心 关于竞争条件或死锁 与引用类型不同,值类型没有引用;因此, 就是没有内存泄漏。

在以下情况使用值类型:

你希望副本有独立的状态,数据才会被使用 跨多线程的代码

在以下情况使用引用类型:

您希望创建共享的、可变的状态。

更多的信息也可以在苹果文档中找到

https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html


额外的信息

Swift值类型保存在堆栈中。在进程中,每个线程都有自己的堆栈空间,因此没有其他线程能够直接访问您的值类型。因此,没有竞争条件、锁、死锁或任何相关的线程同步复杂性。

值类型不需要动态内存分配或引用计数,这两者都是昂贵的操作。同时,值类型上的方法是静态分派的。就性能而言,这为值类型创造了巨大的优势。

作为提醒,这里有一个Swift列表

值类型:

结构体 枚举 元组 基本类型(Int, Double, Bool等) 集合(数组,字符串,字典,集合)

引用类型:

类 任何来自NSObject的东西 函数 关闭

其他回答

在这些回答中没有注意到的一点是,持有类和结构的变量可以是let,同时仍然允许对对象的属性进行更改,而对于结构则不能这样做。

如果你不希望变量指向另一个对象,但仍然需要修改对象,即在有许多实例变量的情况下,你希望一个接一个地更新,这是很有用的。如果它是一个结构,你必须允许变量被重置为另一个对象使用var,因为在Swift常量值类型正确地允许零突变,而引用类型(类)不这样做。

许多Cocoa api需要NSObject子类,这迫使你使用class。但除此之外,你可以使用以下苹果Swift博客中的案例来决定是使用struct / enum值类型还是类引用类型。

https://developer.apple.com/swift/blog/?id=10

As struct are value types and you can create the memory very easily which stores into stack.Struct can be easily accessible and after the scope of the work it's easily deallocated from the stack memory through pop from the top of the stack. On the other hand class is a reference type which stores in heap and changes made in one class object will impact to other object as they are tightly coupled and reference type.All members of a structure are public whereas all the members of a class are private.

struct的缺点是不能被继承。

在Swift中,引入了一种新的编程模式,称为面向协议编程。

创建型模式:

在swift中,Struct是一种自动克隆的值类型。因此,我们可以免费获得实现原型模式所需的行为。

而类是引用类型,在赋值过程中不会自动克隆。为了实现原型模式,类必须采用NSCopying协议。


浅拷贝只复制指向那些对象的引用,而深拷贝复制对象的引用。


为每种引用类型实现深度复制已成为一项乏味的任务。如果类包含进一步的引用类型,我们必须为每个引用属性实现原型模式。然后我们需要通过实现NSCopying协议复制整个对象图。

class Contact{
  var firstName:String
  var lastName:String
  var workAddress:Address // Reference type
}

class Address{
   var street:String
   ...
} 

通过使用结构体和枚举,我们使我们的代码更简单,因为我们不需要实现复制逻辑。

从值类型和引用类型的角度来回答这个问题,从苹果博客的这篇文章来看,它看起来非常简单:

使用值类型[例如struct, enum]: 用==比较实例数据是有意义的 你希望副本有独立的状态 这些数据将在代码中跨多个线程使用 在以下情况下使用引用类型[例如class]: 比较实例标识和===是有意义的 您希望创建共享的、可变的状态

正如在那篇文章中提到的,没有可写属性的类将与结构体的行为相同,但有一点需要注意:结构体最适合线程安全模型——这是现代应用程序架构中日益迫切的需求。