2016-02-02 20 views
10

Tôi hiểu rằng các bộ dữ liệu của Swift phục vụ, ví dụ, như một cách đơn giản cho một hàm trả về nhiều giá trị. Tuy nhiên, ngoài "khía cạnh đơn giản" này, tôi không thấy rõ bất kỳ sự cần thiết nào của việc sử dụng các bộ dữ liệu thay vì cấu trúc.Tuple vs Struct trong Swift

Vì vậy, câu hỏi của tôi: về mặt thiết kế, có bất kỳ trường hợp nào mà bộ nhớ rõ ràng là lựa chọn tốt hơn cấu trúc không?

+2

Tôi tự nhủ rằng các bộ dữ liệu chỉ hữu ích cho các cấu trúc dữ liệu chỉ được sử dụng cục bộ; nếu không thì tốt hơn là nên có tất cả các cấu trúc dữ liệu được định nghĩa đúng và "được gắn nhãn" làm cấu trúc hoặc các lớp, thay vì để chúng "trôi nổi xung quanh thành các bộ ẩn danh". Nhưng tôi không chắc mình sẽ không sai ... – George

+1

Tôi nghĩ rằng khía cạnh đơn giản là những gì nó là tất cả về :) Không cần phải xác định một cấu trúc, ít mã, nhanh chóng. Swift có nhiều tính năng phục vụ mục đích đơn giản. –

Trả lời

6

Câu hỏi này của một "thảo luận" tự nhiên hơn một chút, nhưng Tôi sẽ thêm hai điểm có lợi cho đôi khi thích tuples hơn cấu trúc.


phù hợp Equatable Native cho các bộ kích thước hạn chế

Trong Swift 2.2, tuples lên đến kích thước 6 sẽ natively equatable, cho rằng đó là thành viên là equatable

Điều này có nghĩa là bộ đôi đôi khi sẽ là lựa chọn tự nhiên qua việc sử dụng các cấu trúc nhỏ hơn trong phạm vi giới hạn.

Ví dụ: xem xét ví dụ sau đây, sử dụng (1): một cấu trúc

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): một tuple

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

Generic quyền truy cập vào các bộ gõ khác nhau: linh hoạt hơn so với cấu trúc kiểu khác nhau

Từ phía trên (so sánh các chức năng ==), nó cũng là appare nt rằng các bộ dữ liệu có thể dễ dàng làm việc trong ngữ cảnh của các generics, vì chúng ta có thể truy cập các thuộc tính thành viên ẩn danh của chúng bằng cách sử dụng các hậu tố .0, .1 ...; trong khi đối với một cấu trúc, cách dễ nhất để bắt chước hành vi này nhanh chóng trở nên khá phức tạp, các công cụ cần thiết như sự quan sát thời gian chạy và như vậy, xem e.g. this.

+0

Điều đó thật thú vị. Cảm ơn bạn – George

+0

Tuples trong params chức năng và trả về có thể làm cho nó thực sự rõ ràng những gì các chức năng sẽ làm. 'func multiply (aNumber number: Int, by anotherNumber: Int) -> Int'. Như một 'struct', điều này sẽ không rõ ràng chút nào. 'func multiply (haiNumber: TwoNumbersStruct) -> Int' –

0

Hãy xem xét điều này, java đến mục tiêu-C. Khi bạn phải cắm bản thân vào loại nguồn dữ liệu này trong dự án của bạn (vì bạn có một basecode khổng lồ trong android và không muốn hoặc không thể làm mọi thứ từ đầu), bạn thấy mình có nguồn dữ liệu kiểu java (ví dụ như hashmap) , về cơ bản typedef từ các kiểu mục tiêu-c. Đây không phải là dễ dàng cắm vào nhanh chóng tùy thuộc vào những gì bạn có, nếu bạn muốn có một mảng tốt đẹp cho collectionview của bạn, một loạt các bộ dữ liệu sẽ được lấp đầy bởi nguồn dữ liệu java có thể được tốt đẹp. Một chút mẫu mã để minh họa điều này:

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

Sau đó bạn có thể nhận được dữ liệu của bạn như thế này (trong phương pháp collectionview của bạn):

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

Nhưng điều gì ngăn cản bạn xác định cấu trúc và sử dụng cấu trúc đó trong mảng, thay vì sử dụng bộ tuple? Và tại sao một tuple tốt hơn cấu trúc? Dường như với tôi rằng tuple chỉ làm cho mã khó đọc hơn (đó là chủ quan, tôi biết). – George

+0

Sử dụng tuple đã là một nỗi đau trong ass và bạn muốn sử dụng một struct cho điều này? Điều này chỉ dành cho ô tiêu đề, tôi cho phép bạn hình dung ra nó giống như thế nào khi bạn phải điền vào mảng ô bình thường. Làm cách nào để có một tham số được đặt tên làm cho mã khó đọc hơn? –

+0

Bạn chỉ có thể xác định cấu trúc có tên HeaderData (ví dụ) với các thành viên varName, param và varId. Bạn có: var headerArray: [HeaderData] = [] – George

Các vấn đề liên quan