一般来说,Swift或OOP中元组的典型用例是什么?

时间:2015-04-16 19:06:47

标签: oop swift design-patterns tuples object-oriented-analysis

我在大约4个月前在Swift开始了一个新的iOS项目,只是为了学习这门语言。虽然我一直在开发它,但我发现自己几乎从未在整个程序中使用元组。这是因为我真的习惯了没有元组的Java和Objective-C。

我听说过一些关于元组的好东西,Apple似乎非常兴奋将它们添加到Swift中,但似乎我很难找到一个非常有用的案例。

到目前为止,我理解并使用它们:快速类替代品。而不是为了保持一些属性的唯一目的而创建一个新类,而是使用元组代替。但即便如此,我也只使用过一次元组,因为很多时候这些属性会相互影响,因此那些改变这些属性的方法最好包含在具有这些属性的类中。这真的是一个优势吗?

但在OOP(或Swift)中使用的其他一些非常有用的设计模式是什么?对元组不熟悉的人应该知道什么?

谢谢!

2 个答案:

答案 0 :(得分:4)

标准库中的几个例子可能会有所帮助。

一个常见的需求是不仅从函数返回一个值,而且返回两个不同的值。例如,在_IntegerArithmeticType协议中,有:

static func addWithOverflow(lhs: Self, _ rhs: Self) -> (Self, overflow: Bool)

也就是说,它返回新值,加上一个是否存在溢出的布尔指示符:

let i: UInt8 = 0xFF
let (j, overflow) = UInt8.addWithOverflow(i, 1)
if overflow { println("Oh noes!") }

如果没有元组,您将不得不求助inout获取其中一个结果,或返回另一个结构。

Dictionary集合为其元素,键和值保存两种类型。这些通常捆绑在一起,因此Dictionary将类型Element定义为两者的元组:

struct Dictionary<Key : Hashable, Value> : CollectionType, DictionaryLiteralConvertible {
    typealias Element = (Key, Value)
}

然后,当您遍历字典时,您获得的每个元素都是这一对,并且元组的内置解构允许您方便地将它们分成两个:

// either treat them as a pair:
for element in myDictionary { }

// or destructure them:
for (k, v) in myDictionary { }

现在,从理论上讲,这两个例子都可以通过定义新结构来完成。例如,溢出情况:

struct ResultWithOverflow<T: _IntegerArithmeticType> {
    let value: T
    let overflow: Bool
}

static func addWithOverflow(lhs: Self, _ rhs: Self) -> ResultWithOverflow<Self>

然而,重要的是要理解这里,元组不仅仅被使用,因为必须定义这个额外的结构是很痛苦的(尽管这是真的)。更多的是因为这个额外的结构是混乱的 - 它妨碍了阅读函数。如果你想知道addWithOverflow做了什么,你必须去查看ResultWithOverflow是什么。相反,使用元组,在函数定义中很清楚返回的是什么。

同样地,如果有一个DictionaryElement结构就是字典作为其元素的结构,那么这也会增加复杂性,可能会妨碍理解字典的工作方式。

显然,这是一种权衡,如果你在任何地方使用元组而不是定义适当的结构,那么你将走得太远而使你的代码变得不可读。但是在使用一次性和轻量级的情况下,它们更容易编写并且更易于阅读。

答案 1 :(得分:3)

@Airspeed Velocity给出了一个非常好的答案!我只想添加与switch语句一起使用时有用的元组。例如:

let point = (x: 10, y: 5)

switch point {
    case (10, 5):
        println("Point at (10, 5)")

    case (-10...10, 5):
        println("Point where y = 5 and x lies in the range [-10, 10]")

    case (_, 5) :
        println("Point with y = 5")

    case (let x, _) where x % 2 == 0:
        println("Point with x that is a multiple of 2 (x = \(x))")

    default:
        println("A Point")
}

显然,这不是你真正使用的那种例子,但我认为它展示了元组的一些功能。

Apple的 Swift编程语言讨论了有关元组的更多信息,如果你还没有看到它,请点击链接:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID309