首页 Swift 5.1 学习 (3) : 基本数据类型
文章
取消

Swift 5.1 学习 (3) : 基本数据类型

Swift 中基础的数据类型跟 C语言OC 中也比较相似.

整形(int)

整形 就是我们正常认知中的 整数, 比如 42-23. 他不包含 小数 部分. 整数 包括 有符号正数负数, 也包括 无符号0.

Swift 中提供了 8, 16, 32 和 64 位的 带符号无符号 的整数. 这些整数遵循类似 C语言 的命名约定: | Bit | 无符号 | 有符号 | | —- | —— | —— | | 8 | UInt8 | Int8 | | 16 | UInt16 | Int16 | | 32 | UInt32 | Int32 | | 64 | UInt64 | Int64 |

整形数字范围

可以通过 Intminmax 属性读取 最小值最大值.

1
2
let minValue = UInt8.min  // minValue = 0
let maxValue = UInt8.max  // maxValue = 255

Int

一般情况下, 我们无需选择特定 bit 的数字类型. Swift 提供了一个数据类型 Int, 它的大小跟系统有关.

  • 在 32 位系统中, UInt 相当于 UInt32.
  • 在 64 位系统中, UInt 相当于 UInt64.

注意 只有在有特别的需求, 需要使用与平台字大小的无符号整形数字的时候, 才使用 UInt. 否则, 推荐使用 Int, 即使你已经确定存储的数据是 非负数. 使用统一的 Int 类型可以避免在不同数字类型之间进行转换的情况.

浮点数

浮点数 就是一个 带小数部分 的数字. 比如: 3.1415926, -2.7.

浮点类型 值的范围比 整形 大的多. 并且可以存储比 整形大的多小得多 的数. Swift 提供了 2 种浮点类型:

  • Double 表示一个 64位 的浮点数.
  • Float 表示一个 32位 的浮点数.

注意 Double 的精度至少为 15位 小数, Float 的精度低至 6位 小数. 在开发中使用哪个类型取决于需求的数字的 范围精度. 当 2 种类型都合适的情况下, Double 是首选.

类型安全和类型推断

Swift 是一种 类型安全 的编程语言. 如果一个需要 String 类型作为参数的代码段就不能传入 Int 类型的参数. Swift 是类型安全的, 因此在代码编译阶段会执行类型检查. 如果代码中有类型不匹配就会报 编译错误. 这也可以帮助我们在开发过程中尽早发现错误.

当我们在处理不同类型的值的时候, 类型检查 可以帮助我们避免错误. 当然, 也不是说所有的 常量变量 都必须指定声明其具体类型. 如果我们没有指定数据类型, Swift 就会使用 类型推断 来确定适合的类型. 类型推断 可以使编译器在编译阶段通过检查 常量/变量 来推断其 类型.

如果你给一个新的 常量 赋值为 42 而未声明其类型, 类型推断 就会推断出这个常量为 Int 类型:

1
2
let meaningOfLife = 42
// meaningOfLife 被推断为 Int 类型

同样的, 如果你没有为 浮点型 常量声明其具体类型, 类型推断 会推断其为 Double 类型:

1
2
let pi = 3.14159
// pi 被推断为 Double 类型

如果一个表达式中包含了 整数浮点数, 则会从上下文来推断其为 Double 类型:

1
2
let anotherPi = 3 + 0.14159
// anotherPi 也会被推断为 Double 类型

数字字面值

一个 整形 数字可以被写成一下几种形式: | 进制 | 前缀 | | ——– | —— | | 十进制 | 无前缀 | | 二进制 | 0b | | 八进制 | 0o | | 十六进制 | 0x |

以下几种写法都代表了数字 17:

1
2
3
4
let decimalInteger = 17           // 十进制
let binaryInteger = 0b10001       // 二进制
let octalInteger = 0o21           // 八进制
let hexadecimalInteger = 0x11     // 十六进制

浮点型 数字可以被表示为 十进制(无前缀)十六进制(0x前缀). 浮点型 必须在 小数点 两侧都有 1 个数字 (或者十六进制数字).

  • 十进制 浮点数可以有一个可选的 指数, 由大写或者小写的 e 表示.
  • 十六进制 浮点数必须有一个指数, 用大写或小写的 p 表示.

十进制 的以 exp 为指数的浮点数, 底数 * 10^exp.

  • 1.25e2 等同于 1.25 * 10^2 或者 125.0.
  • 1.25e-2 等同于 1.25 * 10^-2 或者 0.0125.

十六进制 的以 exp 为指数的浮点数, 底数 * 2^exp.

  • 0xFp2 等同于 15 * 2^2 或者 60.0.
  • 0xFp-2 等同于 15 * 2^-2 或者 3.75.

以下几种写法的值都为 12.1857:

1
2
3
let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0

数字还可以加入额外的 "_" 或者 "0" 来提高其可读性, 并且其值不会受到影响:

1
2
3
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1

数字类型转换

在开发中, 尽管已知 常量 或者 变量 存储的是无符号的数字, 也应该尽量使用 Int 类型. 使用默认的 Int 类型就可以在代码中直接做运算.仅仅在特殊需求的情况下选择其他的 整数类型.

整形转换

不同 数值类型常量/变量 所能存储的数值范围是不同的. 一个 Int8常量/变量 可以能存储的数值范围为 -128 ~ 127. 然而, 一个 UInt8 类型的 常量/变量 能够存储数值的范围为 0 ~ 255. 当你尝试把一个超出存储范围的数字存储进 常量/变量 的时候, 代码编译就会报错:

1
2
3
4
5
let cannotBeNegative: UInt8 = -1
// UInt8 不能存储负数, 因此此处会报错

let tooBig: Int8 = Int8.max + 1
// Int8 不能存储一个大于 Int8 最大值的数值, 此处也会报错

因为每种 数值类型 可以存储的数值范围都不想同, 因此必须根据不同情况来选择合适的 数值类型. 这样可以防止隐式转换错误. 且有助于在代码中明确类型转换的意图.

可以通过使用现有 数值 作为目标类型的初始值来初始化一个新的 常量/变量 达到从一个数值类型转换为另一个数值类型的目的. 在下面的事例中, 常量 twoThousandUInt16, 另一个 常量 oneUInt8. 因为他们的 类型不同, 因此无法直接进行 加法运算. 所以在此案例中调用 UInt16(one), 使用 one 的值作为初始值创建一个新得 UInt16 类型的数值, 然后对其和 twoThousand 做运算:

1
2
3
let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)

因为 + 两侧现在都是 UInt16 类型, 因此加法运算是可以进行的. 因为此处是 2 个 UInt16 类型进行运算, 所以运算结果也被推断为 UInt16 类型.

整形和浮点型转换

整形浮点型 之间的转换必须是显式转换.

1
2
3
4
let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi = 3.14159, 被推断为 Double 类型

案例中 常量 three 的值用于创建了一个 Double 类型的值, 此时 + 两边值的类型均为 Double 所以运算是被允许的.

浮点型 转换为 整形 同样的也必须是 显式转换. 整形 可以使用 DoubleFloat 来初始化.

1
2
let integerPi = Int(pi)
// integerPi 等于 3, 并且被推断为 Int 类型

浮点型 被用于初始化为 整形 的时候就会被 截断. 比如: 4.75 会被截断为 4. -3.9 被截断为 -3.

类型别名

类型别名 是现有类型定义的 替代名称. 定义 类型别名 使用 typealias 关键字.

当你希望使用上下文更加合适的名称来引用现有类型时, 类型别名 将会非常有用.

1
typealias AudioSample = UInt16

定义了 类型别名 之后, 就可以在任何可能使用 原始名称 的地方使用 别名.

1
2
var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound 等于 0

此处 AudioSample 是为 UInt16 定义的别名, 因此 AudioSample.min 等价于 UInt16.min, 所以 maxAmplitudeFound 的值为 0.

布尔类型

Swift 有一个基本布尔类型 Bool. 布尔值被成为 逻辑值, 因为他们只能是 . Swift 提供了 2 个布尔常量值 truefalse.

1
2
let orangesAreOrange = true
let turnipsAreDelicious = false

此处因为 orangesAreOrangeturnipsAreDelicious 使用 布尔值 初始化, 因此被推断为 布尔类型. 如果你使用 truefalse 初始化了 常量/变量, 就无需声明其类型为 Bool. 当使用已知类型的值初始化 常量/变量 时候, 类型推断有助于使代码更加简介和易读.

布尔值在处理条件语句时候特别有用, 例如 if 语句:

1
2
3
4
5
6
if turnipsAreDelicious {
    print("Mmm, tasty turnips!")
} else {
    print("Eww, turnips are horrible.")
}
// 打印结果: "Eww, turnips are horrible."

Swift类型安全 可以防止 非布尔值 替换 Bool 类型的情况. 下面的例子就会报错:

1
2
3
4
let i = 1
if i {
    // 此处会报编译错误.
}

但是下面的例子是可以的:

1
2
3
4
let i = 1
if i == 1 {
    // 可以编译通过
}

比较语句 i == 1 结果的类型为 Bool, 因此第二个例子可以正常编译通过.

与其他 类型安全 事例一样, 这种方法避免了意外的错误, 并确保特定代码段的意图始终清晰.

本文由作者按照 CC BY 4.0 进行授权