Кортеж против структуры в 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