Кортеж против структуры в Swift
Я понимаю, что кортежи Swift служат, например, простым способом для функции возвращать несколько значений. Однако, помимо этого "аспекта простоты", я не вижу необходимости использовать кортежи вместо структур.
поэтому мой вопрос: с точки зрения дизайна, есть ли какой-либо сценарий, где кортежи явно лучший выбор, чем структуры?
2 ответов
этот вопрос немного "дискуссионного" характера, но я добавлю два момента в пользу иногда предпочитая кортежи над структурами.
родное Equatable соответствие для ограниченных определенных размер кортежей
в Swift 2.2 кортежи до размера 6 будут изначально эквивалентны, учитывая, что его члены эквивалентны
это означает, что кортежи иногда будет естественным выбором по сравнению с использованием меньших конструкций в ограниченной области.
Е. Г. рассмотрим следующий пример, используя (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
... суффиксы; в то время как для структуры самый простой способ имитировать это поведение быстро становится довольно сложным, требуя таких инструментов, как интроспекция времени выполнения и т. д., см. т. е..
рассмотрим это, java для objective-C. Когда вам нужно подключить себя к этому типу источника данных в вашем проекте (потому что у вас есть огромный базовый код в android и вы не хотите или не можете делать все с нуля), вы оказываетесь с источником данных типов java (например, hashmap), это в основном typedef из типов objective-C. Это нелегко подключить в swift в зависимости от того, что у вас есть, если вы хотите иметь хороший массив для вашего 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