zoukankan      html  css  js  c++  java
  • Swift数据类型简介(二)

    整数

    整数就是没有小数部分的数字,比如42和-23。整数可以是有符号(正、负、零)或者无符号(正、零)。

    Swift 提供了8,16,32和64位的有符号和无符号整数类型。这些整数类型和 C 语言的命名方式很像,比如8位无符号整数类型是UInt8,32位有符号整数类型是Int32。就像 Swift 的其他类型一样,整数类型采用大写命名法。

    整数范围

    你可以访问不同整数类型的min和max属性来获取对应类型的最大值和最小值:

    1. let minValue = UInt8.min // minValue 为 0,是 UInt8 类型的最小值
    2. let maxValue = UInt8.max // maxValue 为 255,是 UInt8 类型的最大值

    Int

    一般来说,你不需要专门指定整数的长度。Swift 提供了一个特殊的整数类型Int,长度与当前平台的原生字长相同:

    • 在32位平台上,Int和Int32长度相同。
    • 在64位平台上,Int和Int64长度相同。


    除非你需要特定长度的整数,一般来说使用Int就够了。这可以提高代码一致性和可复用性。即使是在32位平台上,Int可以存储的整数范围也可以达到-2147483648~2147483647,大多数时候这已经足够大了。

    UInt

    Swift 也提供了一个特殊的无符号类型UInt,长度与当前平台的原生字长相同:

    • 在32位平台上,UInt和UInt32长度相同。
    • 在64位平台上,UInt和UInt64长度相同。
    注意:尽量不要使用UInt,除非你真的需要存储一个和当前平台原生字长相同的无符号整数。除了这种情况,最好使用Int,即使你要存储的值已知是非负的。统一使用Int可以提高代码的可复用性,避免不同类型数字之间的转换,并且匹配数字的类型推测,请参考类型安全和类型推测

    浮点数

    浮点数是有小数部分的数字,比如3.14159,0.1和-273.15。

    浮点类型比整数类型表示的范围更大,可以存储比Int类型更大或者更小的数字。Swift 提供了两种有符号浮点数类型:

    • Double表示64位浮点数。当你需要存储很大或者很高精度的浮点数时请使用此类型。
    • Float表示32位浮点数。精度要求不高的话可以使用此类型。
    注意:Double精确度很高,至少有15位数字,而Float最少只有6位数字。选择哪个类型取决于你的代码需要处理的值的范围。

    类型安全和类型推测

    Swift 是一个类型安全(type safe )的语言。类型安全的语言可以让你清楚地知道代码要处理的值的类型。如果你的代码需要一个String,你绝对不可能不小心传进去一个Int。

    由于 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks),并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。

    当你要处理不同类型的值时,类型检查可以帮你避免错误。然而,这并不是说你每次声明常量和变量的时候都需要显式指定类型。如果你没有显式指定类 型,Swift 会使用类型推测(type inference)来选择合适的类型。有了类型推测,编译器可以在编译代码的时候自动推测出表达式的类型。原理很简单,只要检查你赋的值即可。

    因为有类型推测,和 C 或者 Objective-C 比起来 Swift 很少需要声明类型。常量和变量虽然需要明确类型,但是大部分工作并不需要你自己来完成。

    当你声明常量或者变量并赋初值的时候类型推测非常有用。当你在声明常量或者变量的时候赋给它们一个字面量(literal value 或 literal)即可触发类型推测。(字面量就是会直接出现在你代码中的值,比如42和3.14159。)

    例如,如果你给一个新常量赋值42并且没有标明类型,Swift 可以推测出常量类型是Int,因为你给它赋的初始值看起来像一个整数:

    1. let meaningOfLife = 42 // meaningOfLife 会被推测为 Int 类型

    同理,如果你没有给浮点字面量标明类型,Swift 会推测你想要的是Double:

    1. let pi = 3.14159 // pi 会被推测为 Double 类型

    当推测浮点数的类型时,Swift 总是会选择Double而不是Float。

    如果表达式中同时出现了整数和浮点数,会被推测为Double类型:

    1. let anotherPi = 3 + 0.14159 // anotherPi 会被推测为 Double 类型

    原始值3没有显式声明类型,而表达式中出现了一个浮点字面量,所以表达式会被推测为Double类型。

    数值型字面量

    整数字面量可以被写作:

    • 一个十进制数,没有前缀
    • 一个二进制数,前缀是0b
    • 一个八进制数,前缀是0o
    • 一个十六进制数,前缀是0x


    下面的所有整数字面量的十进制值都是17:

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

    浮点字面量可以是十进制(没有前缀)或者是十六进制(前缀是0x)。小数点两边必须有至少一个十进制数字(或者是十六进制的数字)。浮点字面量还有一个可 选的指数(exponent),在十进制浮点数中通过大写或者小写的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.1875:

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

    数值类字面量可以包括额外的格式来增强可读性。整数和浮点数都可以添加额外的零并且包含下划线,并不会影响字面量:

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

    数值型类型转换

    通常来讲,即使代码中的整数常量和变量已知非负,也请使用Int类型。总是使用默认的整数类型可以保证你的整数常量和变量可以直接被复用并且可以匹配整数 类字面量的类型推测。 只有在必要的时候才使用其他整数类型,比如要处理外部的长度明确的数据或者为了优化性能、内存占用等等。使用显式指定长度的类型可以及时发现值溢出并且可 以暗示正在处理特殊数据。

    整数转换

    不同整数类型的变量和常量可以存储不同范围的数字。Int8类型的常量或者变量可以存储的数字范围是-128~127,而UInt8类型的常量或者变量能存储的数字范围是0~255。如果数字超出了常量或者变量可存储的范围,编译的时候会报错:

    1. let cannotBeNegative: UInt8 = -1 // UInt8 类型不能存储负数,所以会报错
    2. let tooBig: Int8 = Int8.max + 1 // Int8 类型不能存储超过最大值的数,所以会报错

    由于每中整数类型都可以存储不同范围的值,所以你必须根据不同情况选择性使用数值型类型转换。这种选择性使用的方式,可以预防隐式转换的错误并让你的代码中的类型转换意图变得清晰。

    要将一种数字类型转换成另一种,你要用当前值来初始化一个期望类型的新数字,这个数字的类型就是你的目标类型。在下面的例子中,常量 twoThousand是UInt16类型,然而常量one是Uint8类型。它们不能直接相加,因为它们类型不同。所以要调用UInt16(one)来 创建一个新的UInt16数字并用one的值来初始化,然后使用这个新数字来计算:

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

    现在两个数字的类型都是UInt16,可以进行相加。目标常量twoThousandAndOne的类型被推测为UInt16,因为它是两个UInt16值的和。

    SomeType(ofInitialValue)是调用 Swift 构造器并传入一个初始值的默认方法。在语言内部,UInt16有一个构造器,可以接受一个UInt8类型的值,所以这个构造器可以用现有的UInt8来创 建一个新的UInt16。注意,你并不能传入任意类型的值,只能传入UInt16内部有对应构造器的值。不过你可以扩展现有的类型来让它可以接收其他类型 的值(包括自定义类型),请参考扩展

    整数和浮点数转换

    整数和浮点数的转换必须显式指定类型:

    1. let three = 3
    2. let pointOneFourOneFiveNine = 0.14159
    3. let pi = Double(three) + pointOneFourOneFiveNine
    4. // pi 等于 3.14159,所以被推测为 Double 类型

    这个例子中,常量three的值被用来创建一个Double类型的值,所以加号两边的数类型相同。如果不进行转换,两者无法相加。

    浮点数到整数的反向转换同样行,整数类型可以用Double或者Float类型来初始化:

    1. let integerPi = Int(pi) // integerPi 等于 3,所以被推测为 Int 类型

    当用这种方式来初始化一个新的整数值时,浮点值会被截断。也就是说4.75会变成4,-3.9会变成-3。

    注意:结合数字类常量和变量不同于结合数字类字面量。字面量3可以直接和字面量0.14159相加,因为数字字面量本身没有明确的类型。它们的类型只在编译器需要求值的时候被推测。

    类型别名

    类型别名(type aliases)就是给现有类型定义另一个名字。你可以使用typealias关键字来定义类型别名。

    当你想要给现有类型起一个更有意义的名字时,类型别名非常有用。假设你正在处理特定长度的外部资源的数据:

    1. typealias AudioSample = UInt16

    定义了一个类型别名之后,你可以在任何使用原始名的地方使用别名:

    1. var maxAmplitudeFound = AudioSample.min // maxAmplitudeFound 现在是 0

    本例中,AudioSample被定义为UInt16的一个别名。因为它是别名,AudioSample.min实际上是UInt16.min,所以会给maxAmplitudeFound赋一个初值0。

    布尔值

    Swift 有一个基本的布尔(Boolean)类型,叫做Bool。布尔值指逻辑上的(logical),因为它们只能是真或者假。Swift 有两个布尔常量,true和false:

    1. let orangesAreOrange = true
    2. let turnipsAreDelicious = false

    orangesAreOrange和turnipsAreDelicious的类型会被推测为Bool,因为它们的初值是布尔字面量。就像之前提到的 Int和Double一样,如果你创建变量的时候给它们赋值true或者false,那你不需要将常量或者变量声明为Bool类型。初始化常量或者变量的 时候如果所赋的值类型已知,就可以触发类型推测,这让 Swift 代码更加简洁并且可读性更高。

    当你编写条件语句比如if语句的时候,布尔值非常有用:

    1. if turnipsAreDelicious {
    2. println("Mmm, tasty turnips!")
    3. } else {
    4. println("Eww, turnips are horrible.")
    5. }
    6. // 输出 "Eww, turnips are horrible."

    条件语句,例如if,请参考控制流

    如果你在需要使用Bool类型的地方使用了非布尔值,Swift 的类型安全机制会报错。下面的例子会报告一个编译时错误:

    1. let i = 1 if i { // 这个例子不会通过编译,会报错 }

    然而,下面的例子是合法的:

    1. let i = 1 if i == 1 { // 这个例子会编译成功 }

    i == 1的比较结果是Bool类型,所以第二个例子可以通过类型检查。类似i == 1这样的比较,请参考基本操作符

    和 Swift 中的其他类型安全的例子一样,这个方法可以避免错误并保证这块代码的意图总是清晰的。

    元组

    元组(tuples)把多个值组合成一个复合值。元组内的值可以使任意类型,并不要求是相同类型。

    下面这个例子中,(404, "Not Found")是一个描述 HTTP 状态码(HTTP status code)的元组。HTTP 状态码是当你请求网页的时候 web 服务器返回的一个特殊值。如果你请求的网页不存在就会返回一个404 Not Found状态码。

    1. let http404Error = (404, "Not Found") // http404Error 的类型是 (Int, String),值是 (404, "Not Found")

    (404, "Not Found")元组把一个Int值和一个String值组合起来表示 HTTP 状态码的两个部分:一个数字和一个人类可读的描述。这个元组可以被描述为“一个类型为(Int, String)的元组”。

    你可以把任意顺序的类型组合成一个元组,这个元组可以包含所有类型。只要你想,你可以创建一个类型为(Int, Int, Int)或者(String, Bool)或者其他任何你想要的组合的元组。

    你可以将一个元组的内容分解(decompose)成单独的常量和变量,然后你就可以正常使用它们了:

    1. let (statusCode, statusMessage) = http404Error
    2. println("The status code is (statusCode)")
    3. // 输出 "The status code is 404"
    4. println("The status message is (statusMessage)")
    5. // 输出 "The status message is Not Found"

    如果你只需要一部分元组值,分解的时候可以把要忽略的部分用下划线(_)标记:

    1. let (justTheStatusCode, _) = http404Error
    2. println("The status code is (justTheStatusCode)")
    3. // 输出 "The status code is 404"

    此外,你还可以通过下标来访问元组中的单个元素,下标从零开始:

    1. println("The status code is (http404Error.0)") // 输出 "The status code is 404"
    2. println("The status message is (http404Error.1)") // 输出 "The status message is Not Found"

    你可以在定义元组的时候给单个元素命名:

    1. let http200Status = (statusCode: 200, description: "OK")

    给元组中的元素命名后,你可以通过名字来获取这些元素的值:

    1. println("The status code is (http200Status.statusCode)") // 输出 "The status code is 200"
    2. println("The status message is (http200Status.description)") // 输出 "The status message is OK"

    作为函数返回值时,元组非常有用。一个用来获取网页的函数可能会返回一个(Int, String)元组来描述是否获取成功。和只能返回一个类型的值比较起来,一个包含两个不同类型值的元组可以让函数的返回信息更有用。请参考[函数参数与 返回值(06_Functions.html#Function_Parameters_and_Return_Values)。

    注意:元组在临时组织值的时候很有用,但是并不适合创建复杂的数据结构。如果你的数据结构并不是临时使用,请使用类或者结构体而不是元组。请参考类和结构体

    可选

    使用可选(optionals)来处理值可能缺失的情况。可选表示:

    • 有值,等于 x

    或者

    • 没有值
    注意:C 和 Objective-C 中并没有可选这个概念。最接近的是 Objective-C 中的一个特性,一个方法要不返回一个对象要不返回nil,nil表示“缺少一个合法的对象”。然而,这只对对象起作用——对于结构体,基本的 C 类型或者枚举类型不起作用。对于这些类型,Objective-C 方法一般会返回一个特殊值(比如NSNotFound)来暗示值缺失。这种方法假设方法的调用者知道并记得对特殊值进行判断。然而,Swift 的可选可以让你暗示任意类型的值缺失,并不需要一个特殊值。

    来看一个例子。Swift 的String类型有一个叫做toInt的方法,作用是将一个String值转换成一个Int值。然而,并不是所有的字符串都可以转换成一个整数。字符串"123"可以被转换成数字123,但是字符串"hello, world"不行。

    下面的例子使用toInt方法来尝试将一个String转换成Int:

    1. let possibleNumber = "123"
    2. let convertedNumber = possibleNumber.toInt()
    3. // convertedNumber 被推测为类型 "Int?", 或者类型 "optional Int"

    因为toInt方法可能会失败,所以它返回一个可选的(optional)Int,而不是一个Int。一个可选的Int被写作Int?而不是Int。问号 暗示包含的值是可选,也就是说可能包含Int值也可能不包含值。(不能包含其他任何值比如Bool值或者String值。只能是Int或者什么都没有。)

  • 相关阅读:
    “做”的“累”
    举国默哀三天
    AjaxRequest
    客户端表单验证js
    书籍下载链接
    Html元素动态添加方法
    java文件读写操作
    查看oracle当前session
    转一篇有关Java的内存泄露的文章(受益哦)
    《高效能人士的七个习惯》摘录
  • 原文地址:https://www.cnblogs.com/BlogNetSpace/p/3979507.html
Copyright © 2011-2022 走看看