2016-02-02 15 views
10

Ich verstehe, dass Swifts Tupel dienen zum Beispiel als eine einfache Möglichkeit für eine Funktion, mehrere Werte zurückzugeben. Über diesen "Einfachheitsaspekt" hinaus sehe ich jedoch keine Notwendigkeit, Tupel anstelle von Strukturen zu verwenden.Tuple vs Struct in Swift

Daher meine Frage: Gibt es in Bezug auf Design, gibt es ein Szenario, in dem Tupel eindeutig eine bessere Wahl als Strukturen sind?

+2

Ich würde sagen, dass Tupel nur für Datenstrukturen nützlich sind, die nur lokal verwendet werden; ansonsten ist es besser, alle Datenstrukturen als Strukturen oder Klassen richtig definiert und "etikettiert" zu haben, anstatt sie "als anonyme Tupel herumfließen zu lassen". Aber ich bin mir nicht sicher, ob ich nicht falsch liegen würde ... – George

+1

Ich denke, der Einfachheit Aspekt ist, worum es geht :) Keine Notwendigkeit, eine Struktur, weniger Code, schnell zu definieren. Swift hat viele Funktionen, die der Einfachheit dienen. –

Antwort

6

Diese Frage einer leicht „Diskussion“ Natur, sondern Ich werde zwei Punkte hinzufügen, die Tupel gegenüber Strukturen bevorzugen.


Einheimische gleichzusetzen Konformität für eine begrenzte Größe Tupeln

In Swift 2.2 von Tupeln bis Größe 6 nativ gleichzusetzen sein, da es Mitglieder sind gleichzusetzen

Dies bedeutet, dass Tupel manchmal die natürliche Wahl sind über die Verwendung kleinerer Konstrukte in einem begrenzten Umfang.

z. betrachten Sie das folgende Beispiel unter Verwendung (1): eine Struktur

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 
} 

und (2): ein Tupel

/* 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 

generischen Zugriff auf verschiedene Art Tupeln: vielseitiger als für unterschiedliche Art Strukturen

Von den oben genannten (vergleichen Sie die == Funktionen) ist es auch appare Es ist einfach, mit Tupeln im Kontext von Generika zu arbeiten, da wir auf ihre anonymen Member-Eigenschaften unter Verwendung der .0, .1 ... Suffixe zugreifen können; während für eine Struktur der einfachste Weg, dieses Verhalten nachzuahmen, schnell sehr komplex wird und Werkzeuge wie Laufzeit-Introspektion usw. benötigt, siehe e.g. this.

+0

Das ist interessant. Danke – George

+0

Tupel in den Funktionsparametern und Rückkehr können es wirklich klar machen, was die Funktion tun wird. 'func multiplizieren (aNummer: Int, von anotherNumber: Int) -> Int'. Als "Struktur" wäre das überhaupt nicht klar. 'func multipliziere (twoNumbers: TwoNumbersStruct) -> Int' –

0

Betrachten Sie dies, Java zum Ziel-C. Wenn Sie sich mit diesem Typ von Datenquelle in Ihrem Projekt verbinden müssen (weil Sie einen riesigen Basiscode in Android haben und nicht alles von Grund auf neu machen wollen oder wollen), finden Sie sich mit Java Datasource (wie hashmap zum Beispiel) , das sind im Grunde Typdef von Ziel-C-Typen. Dies ist nicht leicht in Swift steckbar, je nachdem, was Sie haben, wenn Sie ein schönes Array für Ihre Sammlung haben möchten, kann ein Array von Tupeln, die von Java-Datenquelle gefüllt werden, nett sein. Eine kleine Probe des Codes dies verdeutlichen:

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)) 
    } 

Anschließend können Sie Ihre Daten wie diese erhalten (in Ihrer Kollektion-Methode):

let time = headerArray[indexPath.section].param 
+0

Aber was verhindert, dass Sie eine Struktur definieren und sie im Array verwenden, anstatt das Tupel zu verwenden? Und warum ist ein Tupel besser als eine Struktur? Es scheint mir, dass das Tupel den Code nur schwieriger lesbar macht (was subjektiv ist, weiß ich). – George

+0

Die Verwendung eines Tupels war schon ein Schmerz in den Arsch und Sie möchten eine Struktur dafür verwenden? Dies ist nur für die Header-Zelle, ich lasse Sie sich vorstellen, wie es ist, wenn Sie das normale Zellenfeld füllen müssen. Wie kann ein benannter Parameter den Code schwerer lesbar machen? –

+0

Sie können einfach eine Struktur namens HeaderData (zum Beispiel) mit den Membern varName, param und varId definieren. Das haben Sie: var headerArray: [HeaderData] = [] – George