结构与类的迅速语言
从苹果书“结构和类之间最重要的差异之一是结构总是在你的代码中传递时被复制,但是类是通过引用传递的。
任何人都可以让我明白这是什么意思,对我来说,类和结构似乎是一样的。
这是一个class
的例子。 请注意,名称更改时如何更新由两个variables引用的实例。 Bob
现在是Sue
, Bob
曾经引用过的所有地方。
class SomeClass { var name: String init(name: String) { self.name = name } } var aClass = SomeClass(name: "Bob") var bClass = aClass // aClass and bClass now reference the same instance! bClass.name = "Sue" println(aClass.name) // "Sue" println(bClass.name) // "Sue"
现在用一个struct
我们看到这些值被复制,每个variables保持它自己的一组值。 当我们将名称设置为Sue
, aStruct
中的Bob
结构不会被更改。
struct SomeStruct { var name: String init(name: String) { self.name = name } } var aStruct = SomeStruct(name: "Bob") var bStruct = aStruct // aStruct and bStruct are two structs with the same value! bStruct.name = "Sue" println(aStruct.name) // "Bob" println(bStruct.name) // "Sue"
所以为了表示一个有状态的复杂实体,一个class
是真棒的。 但是对于只是一些测量或相关数据的值而言, struct
更有意义,因此您可以轻松地复制这些值并使用它们进行计算或修改值,而不必担心副作用。
类和结构都可以做到:
- 定义属性来存储值
- 定义提供function的方法
- 延长
- 符合协议
- 定义先验者
- 定义下标以提供对其variables的访问
只有class级可以做:
- 遗产
- types铸造
- 定义deinitialisers
- 允许多个引用的引用计数。
struct
是值types。 这意味着如果将结构的实例复制到另一个variables中,它只是复制到variables中。
值types的示例
struct Resolution { var width = 2 var height = 3 } let hd = Resolution(width: 1920, height: 1080) var cinema = hd //assigning struct instance to variable println("Width of cinema instance is \(cinema.width)")//result is 1920 println("Width of hd instance is \(hd.width)")//result is 1920 cinema.width = 2048 println("Width of cinema instance is \(cinema.width)")//result is 2048 println("Width of hd instance is \(hd.width)")//result is 1920
类是引用types。 这意味着,如果将一个类的实例赋值给一个variables,它将只保存对实例的引用而不是副本 。
结构和类之间的主要区别:
- 结构不能从其他typesinheritance。
- 类使用types转换将类视为超类或子类,以及检查协议的采用。 结构只能使用协议采用部分。
- 结构没有去初始化器。
- 结构不能有多个对同一个实例的引用
如果你在苹果手册中看得更远,你会看到这个部分:“结构和枚举是值types”
在本节中,您将看到:
“let hd = Resolution(width:1920,height:1080)var cinema = hd这个例子声明了一个叫做hd的常量,并将其设置为Resolution实例初始化为全高清video的宽度和高度(1920像素宽×1080像素高)。
然后它声明一个名为cinema的variables,并将其设置为hd的当前值。 由于“解决scheme”是一个结构,现有实例的一个副本被创build,并且这个新副本被分配给电影院。 尽pipe现在高清电影和高清电影拥有相同的宽度和高度,但在幕后却是两个完全不同的例子。
接下来,将电影的宽度属性修改为用于数字电影投影的宽度稍宽的2K标准(宽2048像素,高1080像素):
电影宽度= 2048检查电影的宽度属性显示它确实已经改变为2048:
println(“电影是现在(电影宽度)像素宽”)/ /打印“电影现在是2048像素宽但是,原始高清实例的宽度属性仍然旧1920年的价值:
println(“高清仍然(高清宽)像素宽”)/打印“高清仍然1920像素宽”
当电影获得当前hd值时,存储在hd中的值被复制到新的电影实例中。 最终结果是两个完全分离的实例,它们恰好包含相同的数值。 因为它们是不同的实例,所以将电影的宽度设置为2048不会影响存储在hd中的宽度。“
摘录自:苹果公司“Swift编程语言”,iBooks。 https://itun.es/us/jEUH0.l
这是结构和类之间最大的区别。 结构被复制并引用类。
以上答案是正确的我希望我的回答会帮助不明白以上答案的人。
那么在Swift中有两种types的对象
- 结构
- 类
他们之间的主要区别是
- 结构是值types
- 类是引用types
比如这里的代码很好理解。
struct SomeStruct { var a : Int; init(_ a : Int) { self.a = a } } class SomeClass { var a: Int; init(_ a: Int) { self.a = a } } var x = 11 var someStruct1 = SomeStruct(x) var someClass1 = SomeClass(x) var someStruct2 = someStruct1 var someClass2 = someClass1 someClass1.a = 12 someClass2.a // answer is 12 because it is referencing to class 1 property a someStruct1.a = 14 someStruct2.a // answer is 11 because it is just copying it not referencing it
这是主要的区别,但我们也有分歧。
类
- 必须声明初始程序(constructer)
- 有deinitialisers
- 可以从其他类inheritance
结构
- 它为您提供免费的初始化程序,如果您的免费初始化程序将被您的已声明的初始程序程序覆盖,则您不必声明初始程序
- 不要有deinitialiser
- 不能从其他结构inheritance
为了理解Structs和Classes之间的区别,我们需要知道值和引用types之间的主要区别。 结构是值types,这意味着它们的每一个变化只会修改这个值,类是引用types,引用types中的每一个变化都会修改在那个内存或引用的地方分配的值。 例如:
让我们从一个类开始,这个类符合Equatable只是为了能够比较实例,我们创build一个名为pointClassInstanceA
实例,而另一个名为pointClassInstanceB
我们将类A分配给B类,现在断言说它们是相同的…
class PointClass: Equatable { var x: Double var y: Double init(x: Double, y: Double) { self.x = x self.y = y } static func == (lhs: PointClass, rhs: PointClass) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y } } var pointClassInstanceA = PointClass(x: 0, y: 0) var pointClassInstanceB = pointClassInstanceA assert(pointClassInstanceA==pointClassInstanceB) pointClassInstanceB.x = 10 print(pointClassInstanceA.x) //this prints 10
好吧,这里发生了什么,为什么如果我们只是改变了pointsClassInstanceB的x值,它也改变了pointClassInstanceA的x值? 好吧,这显示了引用types是如何工作的,当我们将实例A赋值为实例B的值,然后修改其中一个的X时,它将改变这两个X,因为它们共享相同的引用,并且改变了那个值参考。
让我们做一样的,但是有一个结构
struct PointStruct: Equatable { var x: Double var y: Double init(x: Double, y: Double) { self.x = x self.y = y } static func == (lhs: PointStruct, rhs: PointStruct) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y } } var pointStructInstanceA = PointStruct(x: 0, y: 0) var pointStructInstanceB = pointStructInstanceA assert(pointStructInstanceA==pointStructInstanceB) pointStructInstanceB.x = 100 print(pointStructInstanceA.x) //this will print 0
我们的结构与我们的类基本相同,但是现在您可以看到,当您打印pointStructInstanceA的x值时,这种情况并没有改变,这是因为值types的工作方式不同,其中一个实例的每个更改都将是“独立“,不会影响对方。
Swiftbuild议使用更多的值types,你可以告诉他们的库是基于结构的,以避免引用types带来的问题,比如无意中修改了一个值等等。结构是继续Swift的途径。 希望能帮助到你。
下面是一个精确地显示结构和类之间差异的例子。
书面代码在操场上的截图
struct Radio1{ var name:String // init(name:String) { // self.name = name // } } struct Car1{ var radio:Radio1? var model:String } var i1 = Car1(radio: Radio1(name:"murphy"),model:"sedan") var i2 = i1 //since car instance i1 is a struct and //this car has every member as struct , //all values are copied into i2 i2.radio?.name //murphy i2.radio = Radio1(name: "alpha") i2.radio?.name //alpha i1.radio?.name //murphy //since Radio1 was struct , //values were copied and thus // changing name of instance of Radio1 in i2 //did not bring change in i1 class Radio2{ var name:String init(name:String) { self.name = name } } struct Car2{ var radio:Radio2? var model:String } var i3 = Car2(radio: Radio2(name:"murphy"),model:"sedan") //var radioInstance = Radio2(name: "murphy") //var i3 = Car2(radio: radioInstance,model:"sedan") var i4 = i3 //since i3 is instance of struct //everything is copied to i4 including reference of instance of Radio2 //because Radio2 is a class i4.radio?.name //murphy i4.radio?.name="alpha" i4.radio?.name //alpha i3.radio?.name //alpha //since Radio2 was class, //reference was copied and //thus changing name of instance //of Radio2 in i4 did bring change in i3 too //i4.radio?.name //i4.radio = Radio2(name: "alpha") //i4.radio?.name // //i3.radio?.name
通常(在大多数编程语言中),对象是存储在堆上的数据块,然后对这些块的引用(通常是指针)包含正在使用的name
来访问这些数据块。 该机制允许通过复制引用(指针)的值来共享堆中的对象。 这不是基本数据types(如Integers)的情况,这是因为创build引用所需的内存几乎与对象相同(在此情况下为整数值)。 因此,在大型物体的情况下,它们将被视为值而不是参考。
即使使用String和Array对象,Swift也使用struct来提高性能。
这里有一个非常好的阅读