【问题标题】:Tuple vs Struct in SwiftSwift 中的元组与结构
【发布时间】:2016-02-02 12:43:48
【问题描述】:

我知道 Swift 的元组可以作为函数返回多个值的一种简单方式。但是,除了这个“简单性方面”之外,我看不到使用元组而不是结构的任何必要性。

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

【问题讨论】:

  • 我自己会说,元组仅对仅在本地使用的数据结构有用;否则最好将所有数据结构正确定义并“标记”为结构或类,而不是让它们“作为匿名元组浮动”。但我只是不确定我不会错......
  • 我认为简单的方面就是它的全部意义:) 无需定义结构,代码更少,速度更快。 Swift 有许多简单的特性。

标签: swift struct tuples


【解决方案1】:

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


有限大小元组的原生 Equatable 一致性

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

这意味着元组有时会成为在有限范围内使用较小构造的自然选择。

例如考虑下面的例子,使用(1): a structure

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 访问它们的匿名成员属性...后缀;而对于结构体,模仿这种行为的最简单方法很快就会变得相当复杂,需要运行时自省等工具,请参阅e.g. this

【讨论】:

  • 这很有趣。谢谢
  • 函数参数和返回中的元组可以非常清楚地说明函数将做什么。 func multiply(aNumber number : Int, by anotherNumber : Int) -&gt; Int。作为struct,这根本不清楚。 func multiply(twoNumbers : TwoNumbersStruct) -&gt; Int
【解决方案2】:

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

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)

现在可以像这样访问成员。它看起来和结构一样。

    state.system.someSetting
    state.user.accessLevel

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

【讨论】:

    【解决方案3】:

    考虑到这一点,java 到 Objective-C。 当您必须将自己插入项目中的这种类型的数据源时(因为您在 android 中有大量的基本代码并且不想或不能从头开始做所有事情),您会发现自己使用 java 类型的数据源(例如 hashmap),这些基本上是来自objective-c类型的typedef。 这并不容易根据你得到的东西快速插入,如果你想为你的collectionview有一个很好的数组,一个由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
    

    【讨论】:

    • 但是是什么阻止你定义一个结构并在数组中使用它,而不是使用元组呢?为什么元组比结构更好?在我看来,元组只是让代码更难阅读(我知道这是主观的)。
    • 使用元组已经很麻烦了,您想为此使用结构吗?这仅适用于标题单元格,我让您想象当您必须填充普通单元格数组时会是什么样子。命名参数如何让代码更难阅读?
    • 您可以只定义一个名为 HeaderData 的结构(例如),其中包含成员 varName、param 和 varId。你有: var headerArray: [HeaderData] = []
    • 是的,我同意它没有回答他的问题,即为什么元组一定比结构更好。是纯语法糖的问题吗?
    • @thibautnoah 您可以将元组用于函数的返回之外。此外,您显然可以从函数返回结构。可以说,该结构将被更好地定义和考虑,因为它需要开发人员声明它。所以,问题仍然存在,为什么要使用元组?因为你懒得申报?
    猜你喜欢
    • 2022-06-17
    • 2011-08-16
    • 2014-03-19
    • 2014-08-04
    • 1970-01-01
    • 2020-11-19
    • 2017-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多