为什么Swift会将混合类型数组视为单一类型数组?

时间:2014-12-27 12:05:54

标签: arrays swift types

我最近开始学习Swift,并对数组中的类型处理方式有点混淆。

根据我的理解,数组中可以包含不同的类型。例如:

var arr = [1, 2, 3.0, 4, "myString"]

当我在XCode Playground中写这个并执行println()时,我得到了预期的输出:

[1, 2, 3.0, 4, "String"]

当我删除数组中的String时,我得到以下输出:

[1.0, 2.0, 3.0, 4.0]

为什么Swift将整数视为双精度?当我在Playground中运行以下代码时,这引起了一些困惑:

import UIKit

var arr = [2.0, 3, 4, 5]

for (index, value) in enumerate(arr) {
    arr[index] = value / 2
}    

我期待以下输出:

[1.0, 1, 2, 2]

但输出是:

[1.0, 1.5, 2.0, 2.5]

为什么Swift会自动更改整数类型?

1 个答案:

答案 0 :(得分:2)

  

根据我的理解,数组中可以包含不同的类型。

这种理解是不正确的,数组只能包含一种特定的类型。

实际上,如果您将原始示例键入包含 nothing else 的游乐场(即删除“import UIKit”或“import Cocoa”语句),则无法编译。

Swift标准库中的Array结构如下所示:

struct Array<T> : MutableCollectionType, Sliceable {
    // methods and properties
}

T是“通用占位符”。声明数组时,它将替换为数组包含的类型。但T只能是一种类型。

当您在未指定类型的情况下声明变量时,Swift将尝试“推断”该类型。也就是说,它将从上下文中找出所有可能的类型,并根据(相当广泛的)规则选择一个。

DoubleInt都符合IntegerLiteralConvertible协议。这意味着您可以从1这样的文字创建。但是,Int是默认值。如果你想要Double,你需要明确。

// i will be an Int, the default
let i = 1
// j will also be an Int
let j: Int = 1
// k will be a Double
let k: Double = 1

Double也符合FloatLiteralConvertible,但Int不符合:

// f will be a Double, the default:
let f = 1.0
// or you can declare a Float:
let g: Float = 1.0
// but this won’t work:
let h: Int = 1.0 // compiler error

当你声明一个数组时,Swift会尝试找出数组包含的T类型。它列出了所有可能性并选择了一个。在[1.0, 1, 2]的情况下,Int值排除了包含1.0的可能性,因此选择了T == Double

同样,当您声明[1, 2, 3.0, 4, "String"]时,Double也被排除在外。唯一可行的类型是遵守IntegerLiteralConvertibleFloatLiteralConvertibleStringLiteralConvertible的内容。标准的Swift类型库中的 Nothing 就是这样。

那么为什么你的原始例子有效呢?当你导入UIKit时,它会输入一个类似NSObject的类型。所以斯威夫特选择它。