快速结构中的元组有多么不同? (1)
据我所知,元组和结构都可以通过值发送,而不是通过函数调用中的引用发送,返回,对吧?
另外,我知道如果有
var A : StructureX
var B : StructureX
我知道结构A和B具有相同的Type
,即StructureX
。但...
let A : (Int, String)
let B : (Int, String)
A和B元组是否相同Type
? (2)
使用元组而不是结构有什么好处? (3)
答案 0 :(得分:19)
我发现将Swift Tuples概念化为“#匿名结构”#34;有一些关键的差异。它们的行为类似,但结构具有正式定义,允许更多地控制可变性,而元组允许模式匹配。
元组和结构之间的相似性
typealias
)元组和结构之间的差异
游乐场的一些代码,说明了这些差异和相似之处
// All commented code causes a compilation error. Uncomment to view error messages.
struct StructureX {
let a: Int = 0
var b: String = "string"
}
//
// Struct member variability
//
var structureA: StructureX = StructureX()
let structureB: StructureX = StructureX()
//structureA.a = 2 // declared as a constant, instance is variable
structureA.b = "allowed" // declared as a variable, instance is variable
//structureB.a = 2 // declared as constant, instance is constant
//structureB.b = "not allowed" // declared as constant, instance is constant
structureA = structureB // these are the same type
structureA
//
// A tuple can't be used as a literal to construct a struct.
//
//let StructureC: StructureX = (a: 17, b: "nope")
//
// Typealias a labeled tuple and it can be constructed similarly to a struct
//
typealias StructureT = (a: Int, b: String)
var structureD: StructureT = StructureT(a: 0, b: "asdf")
structureD
//structureD = structureA // but they are distinct types
let emptyTuple: () = () // philosophically, isn't this the definition of Void?
print(emptyTuple) // prints as ()
let single: (Int) = (23)
//let namedSingle: (a: Int) = (a: 42)
//
// Tuple Labeled Member Access
//
var labeledTupleA: (a: Int, b: String) = (a: 0, b: "string")
labeledTupleA.0 = 5
labeledTupleA.a
labeledTupleA
var check: (a: Int, b: String)
check = labeledTupleA // same type
check
//
// Tuples can have functions/closures
//
let labeledTupleB: (Int, String, fun: () -> Void) = (0, "string", { () -> Void in
print("hi")
})
labeledTupleB.1
labeledTupleB.fun()
//labeledTupleB.0 = 10 // this tuple is a constant, so all of its members are constant
//
// Tuples with members of the same type, but differet labels are not of the same type
//
var labeledTupleC: (c: Int, d: String) = (c: -1, d: "fail")
//labeledTupleC = labeledTupleA
//labeledTupleC = labeledTupleB
//
// Tuples with anonymous members matching the type pattern of a labeled member tuple are of equivalent type
//
var unlabeledTuple: (Int, String) = (0, "good")
unlabeledTuple = labeledTupleA
unlabeledTuple = labeledTupleC
//
// Tuples with closures may not refer to sibling members
//
var labeledTupleD: (de: Int, df: (Int) -> Void) = (de: 0, df: { (num: Int) -> Void in
//de += num
//self.de += num
print(num)
})
labeledTupleD.de
labeledTupleD.df(1)
//
// Tuples allow pattern matching, Structs do not
//
//switch structureA {
//case (let i, let s):
// print(i, s)
//default:
// break
//}
switch labeledTupleD {
case (_, let closure):
closure(123)
default:
break
}
答案 1 :(得分:6)
我不确定元组周围的官方术语,但是你声明它们好像是一种特殊的类型:
let A : (Int, String)
也许我们可以说A现在是元组类型的变量?但是,并非所有元组都是相同的。如果声明类型为tuple的变量并尝试为其分配一个参数在计数,序列或类型上不同的元组,则会出现编译器错误。这将失败
let A : (Int, String) = ("Bob", 1234, 4.0)
虽然这很好用:
let A : (Int, String) = (1234, "Bob")
当然,这种强大的类型安全性也适用于结构。
就优点而言,这里有一些关于我所知道的差异的想法。
结构要求您在使用它们之前定义它们。另一方面,元组允许您返回任意值列表。这有用吗?我有一个带有购物车视图控制器的iPad应用程序。购物车视图中有一个摘要视图,可显示购物车在任何给定时间内的当前状态 - 有时只是普通商品,但重新订购的RMA商品和商品也可能在购物车中。我的购物车类上有一个方法,它返回一个包含购物车计数,RMA计数,重新订购计数和总计数的元组。我不必声明一个结构来取回所有四个值。这很方便:
class Cart : NSManagedObject {
...
var totals : (cartCount:Int, rmaCount:Int, reorderedCount:Int, totalCount:Int) {
let cart = ... // Calculate cart count
let rma = ... // Calculate rma count
let reorder = ... // Calculate reorder count
let total = cart + rma + reorder // Add them all up
return (cart, rma, reorder, total)
}
}
在我的购物车视图中:
let cartValues = cart.totals
self.summaryView.cartCountLabel.text = "\(cartValues.cartCount)"
self.summaryView.rmaCountLabel.text = "\(cartValues.rmaCount)"
self.summaryView.reorderCountLabel.text = "\(cartValues.reorderedCount)"
self.summaryView.totalCountLabel.text = "\(cartValues.totalCount)"
可能还有其他原因,但在这种情况下,方便是我最喜欢的元组。