Swift中元组(Tuples),结构体(Struct),枚举(Enums)之间的区别

来源:互联网 发布:淘宝店铺数据分析软件 编辑:程序博客网 时间:2024/06/11 00:23

出自 http://www.swiftmi.com/topic/62.html 

Swift有许多种存储数据方式,你可以用枚举(enums),元组(tuples),结构体(structs),类(classes),在这篇文章中我们将比较枚举、元组、结构体之间区别,首先从最简单的开始-元组(tuples)。

元组(tuple)

元组是多个值组成的复合值类型,例如,你可以定义一个含有整形和字符串的tuple

let amout=(100,"EUR")

当你函数需要返回多个值时,元组这个时候非常有用,你可以使用下标方式来访问元组中的值,如.0,.1以此类推,如下:

let currency = money.1 // "USD"

如果想要给元组多增加些信息,你也可以给元组每个元素命名:

let money = (amount: 100, currency: "USD")

现在,你不仅可以通过.1,而且可以通过.currency访问元素值。

let currency = money.currency // "USD"

如果想给货币增加格式化,我们可以这样做:

 func format(input: (Int,String)) -> String {    return "I have \(input.0) \(input.1) in my wallet"}println(format(money)) // This prints "I have 100 USD in my wallet"

我们的格式化方法在任何(Int,String)类型Tuple都能正常运行。

let mass = (1, "kg")let formatted = format(mass) // "I have 1 kg in my wallet"

结构体(Struct)

事实上,“我有1kg在我的钱包”没有任何意义,因此,接下来我们介绍另外一个结构体类型,结构体(struct)不仅能够有元组类似的数据存储功能,而且能够给结构体定义函数(是元组tuple话,只能定义非成员函数来实现),让我们看看下面的结构体:

struct Money {    let amount: Int    let currency: String}let wallet = Money(amount: 100, currency: "USD")

现在结构体已经有了元组相同的数据存储功能,现在我们来给他增加一个函数

extension Money {  func format() -> String {    return "I have \(self.amount) \(self.currency) in my wallet"  }}println(wallet.format())

如果我们想给重量mass增加一个特有类型,我们可以这样做:

 struct Mass {    let quantity: Int    let unit: String    func format() -> String {        return "I have \(self.quantity) \(self.unit) in my backpack."    }}

现在Money类型不仅有函数,而且有明确的名称,在后面一部分代码种,我们不能像mass那样(1,'kg')传参数.结构体也叫nomial type:即明确了定义类型的名称,如果对象的类型名称相同即相同的类型,在上面的例子代码中,mass和第一次定义的wallet对象有相同的类型成员,但是他们的类型MoneyMass的是属于不同的类型。如果我们调用他们的format函数,会得到不同的结果。

枚举(Enums)

如果你想要将一些值存储在一起,我们可以根据具体情况使用tuple或者struct,当然也可以使用classes,但是如果遇到特殊清空,比如,有些时候我们需要在多项值中选择一个,例如,我们先看看currencies,在之前的代码中,我们用字符串string来做货币单位,假如只允许已知的货币在代码中出现,该怎么办? 我们可以使用enum,假如我们只允许有euros,US dollars 和yen,我们可以建立一个enum类型:

enum Currency {   case EUR   case USD   case YEN}

现在,假如我们有个Current类型的值,我们知道它是EURUSD or YEN 其中的一种,但是现在没有办法表示成员代表其他的具体含义,或者当它同时有多个值时也没办法表示.和struct一样,枚举也能定义函数。

extension Currency {    func symbol() -> String {        switch self {            case .EUR: return "€"            case .USD: return "$"            case .YEN: return "¥"        }    }}

我们可以根据需要增加case,当然也可以给枚举定义只有一个带实际值的成员:

enum Angle {   case Radian(radians: Double)}

上面相当一个结构体:可以增加函数,而且区分了Angle的值与double类型值,如果有需要,我们可以给它增加更多的case(枚举成员)。

该使用哪一种呢?

现在我们总结一下怎么选择tuples,structenums。首先,优先选择tuple如果它能胜任.如果有2个值他们有相同的结构(例如:一对String和Int),如想要体现更加类型安全、“名称化”nominal的类型,那么应该使用struct,例如,你想要区分currencymass.最后,如果需要多个值互斥(比如EUR,USD,YEN只能选一),那么使用枚举enums

本文@solar 译,欢迎拍砖及指正



元组的定义

元组是Objective-C中没有的数据类型,与数组类似,都是表示一组数据的集合,但与数组不同,它的特点是:

  • 元组的长度任意
  • 元组中的数据可以是不同的数据类型
元组的定义很简单,用小括号括起来,然后以逗号隔开就可以了,如:
  1. var userInfo = ("Bannings" ,true, 22)  

读取元组中的数据

这样就创建了一个元组,而想要获取其中的值,则有多种方法,可以直接通过索引来取:
  1. userInfo.0  //Bannings  
  2. userInfo.1  //true  
  3. userInfo.2  //22  
但是这样并不方便,也不直观,那么可以用下面这种方式来访问:
  1. let (name, isMale, age) = userInfo  
  2. name    //Bannings  
  3. isMale  //true  
  4. age     //22  
把已知的userInfo赋给一个全是变量名组成的新的元组,那么就能以变量名去访问元组中的数据了。
还有另外一种方法也能以变量名的方式去访问元组中的数据,那就是在元组初始化的时候就给它一个变量名:
  1. let userInfo = (name:"Bannings" ,isMale:true, age:22)  
  2. userInfo.name       //Bannings  
  3. userInfo.isMale     //true  
  4. userInfo.age        //22  

跳过不关心的值

除此之外,元组还支持“跳过”某些你并不关心的值,只需要用下划线(_)去忽略它们就行了:
  1. let (name,  _, age) = userInfo  
  2. name    //Bannings  
  3. //isMale  这个就不能访问了  
  4. age     //22  
或者是在该元组初始化的时候不给它指定变量名:
  1. let userInfo = (name:"Bannings" ,true, age:22)  
  2. userInfo.name       //Bannings  
  3. //userInfo.isMale     这个就不能访问了  
  4. userInfo.age        //22  

可变元组和不可变元组

用var定义的元组就是可变元组,let定义的就是不可变元组。不管是可变还是不可变元组,元组在创建后就不能对其长度进行增加和删除之类的修改,只有可变元组能在创建之后修改元组中的数据:
  1. var userInfo = (name:"Bannings" ,true, age:22)<span style="white-space:pre">    </span>//定义可变元组  
  2. userInfo.name = "newName"  
  3. userInfo.name   //newName  
  4.   
  5. let userInfo1 = (name:"Bannings" ,true, age:22)<span style="white-space:pre">   </span>//定义不可变元组  
  6. userInfo1.name = "newName"  //报错,不可修改  
需要注意的是,可变元组虽然可以修改数据,但却不能改变其数据的数据类型:
  1. var userInfo = (name:"Bannings" ,true, age:22)  
  2. userInfo.name = 1   //报错  


0 0
原创粉丝点击