玩Swift,来自Java背景,为什么要选择Struct而不是Class?看起来它们是一样的东西,只不过Struct提供的功能更少。那为什么选择它呢?
当前回答
假设我们知道Struct是值类型,Class是引用类型。
如果你不知道值类型和引用类型是什么,那么看看按引用传递和按值传递之间的区别是什么?
根据mikeash的帖子:
... Let's look at some extreme, obvious examples first. Integers are obviously copyable. They should be value types. Network sockets can't be sensibly copied. They should be reference types. Points, as in x, y pairs, are copyable. They should be value types. A controller that represents a disk can't be sensibly copied. That should be a reference type. Some types can be copied but it may not be something you want to happen all the time. This suggests that they should be reference types. For example, a button on the screen can conceptually be copied. The copy will not be quite identical to the original. A click on the copy will not activate the original. The copy will not occupy the same location on the screen. If you pass the button around or put it into a new variable you'll probably want to refer to the original button, and you'd only want to make a copy when it's explicitly requested. That means that your button type should be a reference type. View and window controllers are a similar example. They might be copyable, conceivably, but it's almost never what you'd want to do. They should be reference types. What about model types? You might have a User type representing a user on your system, or a Crime type representing an action taken by a User. These are pretty copyable, so they should probably be value types. However, you probably want updates to a User's Crime made in one place in your program to be visible to other parts of the program. This suggests that your Users should be managed by some sort of user controller which would be a reference type. e.g struct User {} class UserController { var users: [User] func add(user: User) { ... } func remove(userNamed: String) { ... } func ... } Collections are an interesting case. These include things like arrays and dictionaries, as well as strings. Are they copyable? Obviously. Is copying something you want to happen easily and often? That's less clear. Most languages say "no" to this and make their collections reference types. This is true in Objective-C and Java and Python and JavaScript and almost every other language I can think of. (One major exception is C++ with STL collection types, but C++ is the raving lunatic of the language world which does everything strangely.) Swift said "yes," which means that types like Array and Dictionary and String are structs rather than classes. They get copied on assignment, and on passing them as parameters. This is an entirely sensible choice as long as the copy is cheap, which Swift tries very hard to accomplish. ...
我个人不会这样命名我的类。我通常将我的命名为UserManager而不是UserController,但想法是一样的
另外,当你必须重写一个函数的每个实例(即它们没有任何共享功能)时,不要使用类。
所以不是一个类的几个子类。使用几个符合协议的结构体。
使用结构体的另一种合理情况是,当你想对新旧模型进行delta/diff运算时。对于引用类型,你不能开箱即用。对于值类型,突变是不共享的。
其他回答
结构是值类型,类是引用类型
值类型比引用类型快 值类型实例在多线程环境中是安全的 多线程可以改变实例,而不必担心 关于竞争条件或死锁 与引用类型不同,值类型没有引用;因此, 就是没有内存泄漏。
在以下情况使用值类型:
你希望副本有独立的状态,数据才会被使用 跨多线程的代码
在以下情况使用引用类型:
您希望创建共享的、可变的状态。
更多的信息也可以在苹果文档中找到
https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html
额外的信息
Swift值类型保存在堆栈中。在进程中,每个线程都有自己的堆栈空间,因此没有其他线程能够直接访问您的值类型。因此,没有竞争条件、锁、死锁或任何相关的线程同步复杂性。
值类型不需要动态内存分配或引用计数,这两者都是昂贵的操作。同时,值类型上的方法是静态分派的。就性能而言,这为值类型创造了巨大的优势。
作为提醒,这里有一个Swift列表
值类型:
结构体 枚举 元组 基本类型(Int, Double, Bool等) 集合(数组,字符串,字典,集合)
引用类型:
类 任何来自NSObject的东西 函数 关闭
假设我们知道Struct是值类型,Class是引用类型。
如果你不知道值类型和引用类型是什么,那么看看按引用传递和按值传递之间的区别是什么?
根据mikeash的帖子:
... Let's look at some extreme, obvious examples first. Integers are obviously copyable. They should be value types. Network sockets can't be sensibly copied. They should be reference types. Points, as in x, y pairs, are copyable. They should be value types. A controller that represents a disk can't be sensibly copied. That should be a reference type. Some types can be copied but it may not be something you want to happen all the time. This suggests that they should be reference types. For example, a button on the screen can conceptually be copied. The copy will not be quite identical to the original. A click on the copy will not activate the original. The copy will not occupy the same location on the screen. If you pass the button around or put it into a new variable you'll probably want to refer to the original button, and you'd only want to make a copy when it's explicitly requested. That means that your button type should be a reference type. View and window controllers are a similar example. They might be copyable, conceivably, but it's almost never what you'd want to do. They should be reference types. What about model types? You might have a User type representing a user on your system, or a Crime type representing an action taken by a User. These are pretty copyable, so they should probably be value types. However, you probably want updates to a User's Crime made in one place in your program to be visible to other parts of the program. This suggests that your Users should be managed by some sort of user controller which would be a reference type. e.g struct User {} class UserController { var users: [User] func add(user: User) { ... } func remove(userNamed: String) { ... } func ... } Collections are an interesting case. These include things like arrays and dictionaries, as well as strings. Are they copyable? Obviously. Is copying something you want to happen easily and often? That's less clear. Most languages say "no" to this and make their collections reference types. This is true in Objective-C and Java and Python and JavaScript and almost every other language I can think of. (One major exception is C++ with STL collection types, but C++ is the raving lunatic of the language world which does everything strangely.) Swift said "yes," which means that types like Array and Dictionary and String are structs rather than classes. They get copied on assignment, and on passing them as parameters. This is an entirely sensible choice as long as the copy is cheap, which Swift tries very hard to accomplish. ...
我个人不会这样命名我的类。我通常将我的命名为UserManager而不是UserController,但想法是一样的
另外,当你必须重写一个函数的每个实例(即它们没有任何共享功能)时,不要使用类。
所以不是一个类的几个子类。使用几个符合协议的结构体。
使用结构体的另一种合理情况是,当你想对新旧模型进行delta/diff运算时。对于引用类型,你不能开箱即用。对于值类型,突变是不共享的。
一些好处:
由于不可共享,自动线程安全 由于没有isa和refcount,使用更少的内存(实际上通常是堆栈分配) 方法总是静态分派的,所以可以内联(尽管@final可以为类这样做) 更容易推理(不需要“防御性复制”,这是典型的NSArray, NSString等…)出于与线程安全相同的原因
以下是一些值得考虑的其他原因:
struct有一个自动初始化式,你根本不需要在代码中维护它。 struct MorphProperty { var类型:MorphPropertyValueType var键:字符串 var值:AnyObject enum MorphPropertyValueType { case字符串,Int, Double } } var m = MorphProperty(类型:.Int,键:“什么”,值:“blah”)
要在类中得到这个,你必须添加初始化式,并维护初始化式…
Basic collection types like Array are structs. The more you use them in your own code, the more you will get used to passing by value as opposed to reference. For instance: func removeLast(var array:[String]) { array.removeLast() println(array) // [one, two] } var someArray = ["one", "two", "three"] removeLast(someArray) println(someArray) // [one, two, three] Apparently immutability vs. mutability is a huge topic, but a lot of smart folks think immutability -- structs in this case -- is preferable. Mutable vs immutable objects
在Swift中,引入了一种新的编程模式,称为面向协议编程。
创建型模式:
在swift中,Struct是一种自动克隆的值类型。因此,我们可以免费获得实现原型模式所需的行为。
而类是引用类型,在赋值过程中不会自动克隆。为了实现原型模式,类必须采用NSCopying协议。
浅拷贝只复制指向那些对象的引用,而深拷贝复制对象的引用。
为每种引用类型实现深度复制已成为一项乏味的任务。如果类包含进一步的引用类型,我们必须为每个引用属性实现原型模式。然后我们需要通过实现NSCopying协议复制整个对象图。
class Contact{
var firstName:String
var lastName:String
var workAddress:Address // Reference type
}
class Address{
var street:String
...
}
通过使用结构体和枚举,我们使我们的代码更简单,因为我们不需要实现复制逻辑。
推荐文章
- 如何分配一个行动UIImageView对象在Swift
- 在iOS8中使用Swift更改特定视图控制器的状态栏颜色
- 打印一个可变内存地址在swift
- 我如何使一个enum可解码在Swift?
- HTTP请求在Swift与POST方法
- 静态嵌套类在Java,为什么?
- 盎格鲁- ngcloak / ngg展示blink元素
- 如何在Python中使用方法重载?
- 将类代码分离为头文件和cpp文件
- c++中的结构继承
- 获取用户当前位置/坐标
- 'datetime'模块没有'strptime'属性
- 如何在Java中找到给定类的所有子类?
- 在SwiftUI中创建一个VStack填充屏幕宽度
- 移动文本字段时,键盘出现迅速