Swift中的元组与结构

时间:2016-02-02 12:43:48

标签: swift struct tuples

据我所知,Swift的元组用作函数返回多个值的简单方法。但是,除了这个简单的方面之外,我还没有看到使用元组而不是结构的任何必要性。

因此,我的问题是:在设计方面,是否存在元组显然比结构更好的选择?

3 个答案:

答案 0 :(得分:9)

这个有点“讨论”性质的问题,但我会补充两点,有时候更喜欢元组而不是结构。

有限大小元组的Native Equatable一致性

在Swift 2.2中,最大大小为6的元组本身是等同的,因为它的成员是等同的

这意味着元组有时会在有限的范围内使用较小的构造。

E.g。请考虑以下示例,使用(1):结构

struct Foo {
    var a : Int = 1
    var b : Double = 2.0
    var c : String = "3"
}

var a = Foo()
var b = Foo()

// a == b // error, Foo not Equatable

/* we can naturally fix this by conforming Foo to Equatable,
   but this needs a custom fix and is not as versatile as just 
   using a tuple instead. For some situations, the latter will
   suffice, and is to prefer.                                  */
func == (lhs: Foo, rhs: Foo) -> Bool {
    return lhs.a == rhs.a && lhs.b == rhs.b && lhs.c == rhs.c
}

(2):元组

/* This will be native in Swift 2.2 */
@warn_unused_result
public func == <A: Equatable, B: Equatable, C: Equatable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
    return lhs.0 == rhs.0 && lhs.1 == rhs.1 && lhs.2 == rhs.2
}
/* end of native part ...           */

var aa = (1, 2.0, "3")
var bb = (1, 2.0, "3")

aa == bb // true
aa.0 = 2
aa == bb // false

对不同类型元组的通用访问:比不同类型结构更通用

从上面(比较==函数),很明显,元组很容易在泛型的上下文中使用,因为我们可以使用.0,{{.1来访问它们的匿名成员属性1}} ...后缀;而对于结构体,模拟这种行为的最简单方法很快变得非常复杂,需要运行时内省等工具,请参阅e.g. this

答案 1 :(得分:3)

我不知道是否有人对此感兴趣,但是有时我会使用这样的元组来使事情井井有条,这对我来说似乎更具可读性。

List<CarDTO>

鉴于以上内容可能在其他地方定义:

struct SystemState{
    let someSetting: Int
    let someChoice: Int
    let howmuchDoYouNeedForAnExample: String
}

struct UserState{
    let name: String
    let email: String
    let accessLevel: Int
    let blablabla:[String:String]
}
现在可以这样访问

成员。它看起来与结构相同。

typealias State = (system: SystemState,user: UserState)

let theSystemState = SystemState(someSetting: v1, someChoice: v2,
     howmuchDoYouNeedForAnExample: v3)
let theUserState = theSystemState,UserState(name: v4, email: v5, 
    accessLevel: v6, blablabla: v7)


var state: State = (theSystemState,theUserState)

据我所知,使用结构或元组之间并没有真正的区别,只是dfri接受的答案中提到的优点。当您只想传递更易于保持在一起但不需要或从概念上讲没有意义封装到结构中的东西时,元组也提供了简单性。这样,您的代码可以以较小的方式记录您的意图,这可能会使您或其他人将来更容易理解。

答案 2 :(得分:0)

考虑一下,java到objective-C。 当你必须在你的项目中插入自己的这种类型的数据源时(因为你在android中有一个巨大的基本代码并且不想或不能从头开始做任何事情),你会发现自己有java类型的数据源(比如hashmap) ),那些基本上是来自objective-c类型的typedef。 根据你所获得的内容,这不容易在swift中插入,如果你想为你的集合视图提供一个很好的数组,一个由java数据源填充的元组数组可能很好。 一些代码示例来说明这一点:

var myJavaVar = JavaUtilLinkedHashMap()
var headerArray : [(varName : String, param : Int, varId : jlong)] = []


myJavaVar = myStaticMethodToGetMyVar

    //  get var array
    let keySetJava = myJavaVar.keySet().toArray()
    for jCounter in 0..<Int(myJavaVar.size()){
        // id for index
        let key : Int = keySetJava.objectAtIndex(UInt(jCounter)) as! Int
        let varId = jlong.init(key)
        let varName = myMethodToGetName(varId)
        let myParam : Int = myJavaVar.getWithId(keySetJava.objectAtIndex(UInt(jCounter))) as! Int
        // append data to the array
        headerArray.append((varName: categoryName, param : myParam,duration: duration, varId: varId))
    }

然后您可以像这样获取您的数据(在您的collectionview方法中):

 let time = headerArray[indexPath.section].param