1.0 翻譯:lyuka 校對:numbbbbb, stanzhai
2.0 翻譯+校對:EudeMorgen
2.1 翻譯:mmoaay
4.1 翻譯+校對:mylittleswift
本頁包含內(nèi)容:
Swift 語言存在兩種類型:命名型類型和復(fù)合型類型。命名型類型是指定義時(shí)可以給定名字的類型。命名型類型包括類、結(jié)構(gòu)體、枚舉和協(xié)議。比如,一個(gè)用戶定義的類 MyClass
的實(shí)例擁有類型 MyClass
。除了用戶定義的命名型類型,Swift 標(biāo)準(zhǔn)庫也定義了很多常用的命名型類型,包括那些表示數(shù)組、字典和可選值的類型。
那些通常被其它語言認(rèn)為是基本或原始的數(shù)據(jù)型類型,比如表示數(shù)字、字符和字符串的類型,實(shí)際上就是命名型類型,這些類型在 Swift 標(biāo)準(zhǔn)庫中是使用結(jié)構(gòu)體來定義和實(shí)現(xiàn)的。因?yàn)樗鼈兪敲皖愋停虼四憧梢园凑?擴(kuò)展 和 擴(kuò)展聲明 中討論的那樣,聲明一個(gè)擴(kuò)展來增加它們的行為以滿足你程序的需求。
復(fù)合型類型是沒有名字的類型,它由 Swift 本身定義。Swift 存在兩種復(fù)合型類型:函數(shù)類型和元組類型。一個(gè)復(fù)合型類型可以包含命名型類型和其它復(fù)合型類型。例如,元組類型 (Int, (Int, Int))
包含兩個(gè)元素:第一個(gè)是命名型類型 Int
,第二個(gè)是另一個(gè)復(fù)合型類型 (Int, Int)
。
你可以在命名型類型和復(fù)合型類型使用小括號。但是在類型旁加小括號沒有任何作用。舉個(gè)例子,(Int)
等同于 Int
。
本節(jié)討論 Swift 語言本身定義的類型,并描述 Swift 中的類型推斷行為。
類型語法
類型 → 數(shù)組類型 類型 → 字典類型 類型 → 函數(shù)類型 類型 → 類型標(biāo)識 類型 → 元組類型 類型 → 可選類型 類型 → 隱式解析可選類型 類型 → 協(xié)議合成類型 類型 → 元型類型 類型 → 任意類型 類型 → 自身類型 類型 → (類型)
類型注解顯式地指定一個(gè)變量或表達(dá)式的值。類型注解始于冒號 :
終于類型,比如下面兩個(gè)例子:
let someTuple: (Double, Double) = (3.14159, 2.71828)
func someFunction(a: Int) { /* ... */ }
在第一個(gè)例子中,表達(dá)式 someTuple
的類型被指定為 (Double, Double)
。在第二個(gè)例子中,函數(shù) someFunction
的參數(shù) a
的類型被指定為 Int
。
類型注解可以在類型之前包含一個(gè)類型特性的可選列表。
類型注解語法
類型標(biāo)識符引用命名型類型,還可引用命名型或復(fù)合型類型的別名。
大多數(shù)情況下,類型標(biāo)識符引用的是與之同名的命名型類型。例如類型標(biāo)識符 Int
引用命名型類型 Int
,同樣,類型標(biāo)識符 Dictionary<String, Int>
引用命名型類型 Dictionary<String, Int>
。
在兩種情況下類型標(biāo)識符不引用同名的類型。情況一,類型標(biāo)識符引用的是命名型或復(fù)合型類型的類型別名。比如,在下面的例子中,類型標(biāo)識符使用 Point
來引用元組 (Int, Int)
:
typealias Point = (Int, Int)
let origin: Point = (0, 0)
情況二,類型標(biāo)識符使用點(diǎn)語法(.
)來表示在其它模塊或其它類型嵌套內(nèi)聲明的命名型類型。例如,下面例子中的類型標(biāo)識符引用在 ExampleModule
模塊中聲明的命名型類型 MyType
:
var someValue: ExampleModule.MyType
類型標(biāo)識符語法
類型標(biāo)識符 → 類型名稱 泛型參數(shù)子句可選 | 類型名稱 泛型參數(shù)子句可選 . 類型標(biāo)識符 類型名稱 → 標(biāo)識符
元組類型是使用括號括起來的零個(gè)或多個(gè)類型,類型間用逗號隔開。
你可以使用元組類型作為一個(gè)函數(shù)的返回類型,這樣就可以使函數(shù)返回多個(gè)值。你也可以命名元組類型中的元素,然后用這些名字來引用每個(gè)元素的值。元素的名字由一個(gè)標(biāo)識符緊跟一個(gè)冒號 (:)
組成。函數(shù)和多返回值 章節(jié)里有一個(gè)展示上述特性的例子。
當(dāng)一個(gè)元組類型的元素有名字的時(shí)候,這個(gè)名字就是類型的一部分。
var someTuple = (top: 10, bottom: 12) // someTuple 的類型為 (top: Int, bottom: Int)
someTuple = (top: 4, bottom: 42) // 正確:命名類型匹配
someTuple = (9, 99) // 正確:命名類型被自動(dòng)推斷
someTuple = (left: 5, right: 5) // 錯(cuò)誤:命名類型不匹配
所有的元組類型都包含兩個(gè)及以上元素, 除了 Void
。Void
是空元組類型 ()
的別名。
元組類型語法
元組類型 → ( 元組類型元素列表 可選 ) 元組類型元素列表 → 元組類型元素 | 元組類型元素 , 元組類型元素列表 元組類型元素 → 元素名 類型注解 | 類型 元素名 → 標(biāo)識符
函數(shù)類型表示一個(gè)函數(shù)、方法或閉包的類型,它由參數(shù)類型和返回值類型組成,中間用箭頭(->
)隔開:
參數(shù)類型
->返回值類型
參數(shù)類型是由逗號間隔的類型列表。由于參數(shù)類型和返回值類型可以是元組類型,所以函數(shù)類型支持多參數(shù)與多返回值的函數(shù)與方法。
你可以對函數(shù)參數(shù) () -> T
(其中 T 是任何類型)使用 autoclosure
特性。這會自動(dòng)將參數(shù)表達(dá)式轉(zhuǎn)化為閉包,表達(dá)式的結(jié)果即閉包返回值。這從語法結(jié)構(gòu)上提供了一種便捷:延遲對表達(dá)式的求值,直到其值在函數(shù)體中被調(diào)用。以自動(dòng)閉包做為參數(shù)的函數(shù)類型的例子詳見 自動(dòng)閉包 。
函數(shù)類型可以擁有一個(gè)可變長參數(shù)作為參數(shù)類型中的最后一個(gè)參數(shù)。從語法角度上講,可變長參數(shù)由一個(gè)基礎(chǔ)類型名字緊隨三個(gè)點(diǎn)(...
)組成,如 Int...
??勺冮L參數(shù)被認(rèn)為是一個(gè)包含了基礎(chǔ)類型元素的數(shù)組。即 Int...
就是 [Int]
。關(guān)于使用可變長參數(shù)的例子,請參閱 可變參數(shù)。
為了指定一個(gè) in-out
參數(shù),可以在參數(shù)類型前加 inout
前綴。但是你不可以對可變長參數(shù)或返回值類型使用 inout
。關(guān)于這種參數(shù)的詳細(xì)講解請參閱 輸入輸出參數(shù)。
如果一個(gè)函數(shù)類型只有一個(gè)形式參數(shù)而且形式參數(shù)的類型是元組類型,那么元組類型在寫函數(shù)類型的時(shí)候必須用圓括號括起來。比如說,((Int, Int)) -> Void
是接收一個(gè)元組 (Int, Int)
作為形式參數(shù)的函數(shù)的類型。與此相反,不加括號的 (Int, Int) -> Void
是一個(gè)接收兩個(gè) Int
形式參數(shù)并且不返回任何值的函數(shù)的類型。相似地,因?yàn)?Void
是空元組類型 ()
的別名, 函數(shù)類型 (Void)-> Void
與一個(gè)空元組的變量的函數(shù)類型 (()) -> ()
是一樣的。但這些類型和無變量的函數(shù)類型 () -> ()
是不一樣的。
函數(shù)和方法中的變量名并不是函數(shù)類型的一部分。例如:
func someFunction(left: Int, right: Int) {}
func anotherFunction(left: Int, right: Int) {}
func functionWithDifferentLabels(top: Int, bottom: Int) {}
var f = someFunction // 函數(shù) f 的類型為 (Int, Int) -> Void, 而不是 (left: Int, right: Int) -> Void.
f = anotherFunction // 正確
f = functionWithDifferentLabels // 正確
func functionWithDifferentArgumentTypes(left: Int, right: String) {}
func functionWithDifferentNumberOfArguments(left: Int, right: Int, top: Int) {}
f = functionWithDifferentArgumentTypes // 錯(cuò)誤
f = functionWithDifferentNumberOfArguments // 錯(cuò)誤
由于變量標(biāo)簽不是函數(shù)類型的一部分,你可以在寫函數(shù)類型的時(shí)候省略它們。
var operation: (lhs: Int, rhs: Int) -> Int // 錯(cuò)誤
var operation: (_ lhs: Int, _ rhs: Int) -> Int // 正確
var operation: (Int, Int) -> Int // 正確
如果一個(gè)函數(shù)類型包涵多個(gè)箭頭(->),那么函數(shù)類型將從右向左進(jìn)行組合。例如,函數(shù)類型 Int -> Int -> Int
可以理解為 Int -> (Int -> Int)
,也就是說,該函數(shù)類型的參數(shù)為 Int
類型,其返回類型是一個(gè)參數(shù)類型為 Int
,返回類型為 Int
的函數(shù)類型。
函數(shù)類型若要拋出錯(cuò)誤就必須使用 throws
關(guān)鍵字來標(biāo)記,若要重拋錯(cuò)誤則必須使用 rethrows
關(guān)鍵字來標(biāo)記。throws
關(guān)鍵字是函數(shù)類型的一部分,非拋出函數(shù)是拋出函數(shù)函數(shù)的一個(gè)子類型。因此,在使用拋出函數(shù)的地方也可以使用不拋出函數(shù)。拋出和重拋函數(shù)的相關(guān)描述見章節(jié) 拋出函數(shù)與方法 和 重拋函數(shù)與方法。
非逃逸閉包函數(shù)不能作為參數(shù)傳遞到另一個(gè)非逃逸閉包函數(shù)的參數(shù)。這樣的限制可以讓 Swift 在編譯時(shí)就完成更多的內(nèi)存訪問沖突檢查, 而不是在運(yùn)行時(shí)。舉個(gè)例子:
let external: (Any) -> Void = { _ in () }
func takesTwoFunctions(first: (Any) -> Void, second: (Any) -> Void) {
first(first) // 錯(cuò)誤
second(second) // 錯(cuò)誤
first(second) // 錯(cuò)誤
second(first) // 錯(cuò)誤
first(external) // 正確
external(first) // 正確
}
在上面代碼里,takesTwoFunctions(first:second:)
的兩個(gè)參數(shù)都是函數(shù)。 它們都沒有標(biāo)記為 @escaping
, 因此它們都是非逃逸的。
上述例子里的被標(biāo)記為“錯(cuò)誤”的四個(gè)函數(shù)調(diào)用會產(chǎn)生編譯錯(cuò)誤。因?yàn)榈谝粋€(gè)和第二個(gè)參數(shù)是非逃逸函數(shù),它們不能夠被當(dāng)作變量被傳遞到另一個(gè)非閉包函數(shù)參數(shù)。與此相反, 標(biāo)記“正確”的兩個(gè)函數(shù)不回產(chǎn)生編譯錯(cuò)誤。這些函數(shù)調(diào)用不會違反限制, 因?yàn)?外部(external)
不是 takesTwoFunctions(first:second:)
里的一個(gè)參數(shù)。
如果你需要避免這個(gè)限制, 標(biāo)記其中之一的參數(shù)為逃逸, 或者使用 withoutActuallyEscaping(_:do:)
函數(shù)臨時(shí)地轉(zhuǎn)換非逃逸函數(shù)的其中一個(gè)參數(shù)為逃逸函數(shù)。關(guān)于避免內(nèi)存訪問沖突,可以參閱內(nèi)存安全。
函數(shù)類型語法
函數(shù)類型 → 特性列表可選 函數(shù)類型子句 throws可選 -> 類型 函數(shù)類型 → 特性列表可選 函數(shù)類型子句 rethrows- -> 類型 函數(shù)類型子句 → (-)- 函數(shù)類型子句 → (函數(shù)類型參數(shù)列表...-可選)- 函數(shù)類型參數(shù)列表 → 函數(shù)類型參數(shù) | 函數(shù)類型參數(shù), 函數(shù)類型參數(shù)列表 函數(shù)類型參數(shù) → 特性列表可選 輸入輸出參數(shù)可選 類型 | 參數(shù)標(biāo)簽 類型注解 參數(shù)標(biāo)簽 → 標(biāo)識符
Swift 語言為標(biāo)準(zhǔn)庫中定義的 Array<Element>
類型提供了如下語法糖:
[
類型
]
換句話說,下面兩個(gè)聲明是等價(jià)的:
let someArray: Array<String> = ["Alex", "Brian", "Dave"]
let someArray: [String] = ["Alex", "Brian", "Dave"]
上面兩種情況下,常量 someArray
都被聲明為字符串?dāng)?shù)組。數(shù)組的元素也可以通過下標(biāo)訪問:someArray[0]
是指第 0 個(gè)元素 "Alex"
。
你也可以嵌套多對方括號來創(chuàng)建多維數(shù)組,最里面的方括號中指明數(shù)組元素的基本類型。比如,下面例子中使用三對方括號創(chuàng)建三維整數(shù)數(shù)組:
var array3D: [[[Int]]] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
訪問一個(gè)多維數(shù)組的元素時(shí),最左邊的下標(biāo)指向最外層數(shù)組的相應(yīng)位置元素。接下來往右的下標(biāo)指向第一層嵌入的相應(yīng)位置元素,依次類推。這就意味著,在上面的例子中,array3D[0]
是 [[1, 2], [3, 4]]
,array3D[0][1]
是 [3, 4]
,array3D[0][1][1]
則是 4
。
關(guān)于 Swift 標(biāo)準(zhǔn)庫中 Array
類型的詳細(xì)討論,請參閱 數(shù)組。
數(shù)組類型語法
數(shù)組類型 → [ 類型 ]
Swift 語言為標(biāo)準(zhǔn)庫中定義的 Dictionary<Key, Value>
類型提供了如下語法糖:
[
鍵類型
:值類型
]
換句話說,下面兩個(gè)聲明是等價(jià)的:
let someDictionary: [String: Int] = ["Alex": 31, "Paul": 39]
let someDictionary: Dictionary<String, Int> = ["Alex": 31, "Paul": 39]
上面兩種情況,常量 someDictionary
被聲明為一個(gè)字典,其中鍵為 String
類型,值為 Int
類型。
字典中的值可以通過下標(biāo)來訪問,這個(gè)下標(biāo)在方括號中指明了具體的鍵:someDictionary["Alex"]
返回鍵 Alex
對應(yīng)的值。如果鍵在字典中不存在的話,則這個(gè)下標(biāo)返回 nil
。
字典中鍵的類型必須符合 Swift 標(biāo)準(zhǔn)庫中的 Hashable
協(xié)議。
關(guān)于 Swift 標(biāo)準(zhǔn)庫中 Dictionary
類型的詳細(xì)討論,請參閱 字典。
字典類型語法
Swift 定義后綴 ?
來作為標(biāo)準(zhǔn)庫中的定義的命名型類型 Optional<Wrapped>
的語法糖。換句話說,下面兩個(gè)聲明是等價(jià)的:
var optionalInteger: Int?
var optionalInteger: Optional<Int>
在上述兩種情況下,變量 optionalInteger
都被聲明為可選整型類型。注意在類型和 ?
之間沒有空格。
類型 Optional<Wrapped>
是一個(gè)枚舉,有兩個(gè)成員,none
和 some(Wrapped)
,用來表示可能有也可能沒有的值。任意類型都可以被顯式地聲明(或隱式地轉(zhuǎn)換)為可選類型。如果你在聲明或定義可選變量或?qū)傩缘臅r(shí)候沒有提供初始值,它的值則會自動(dòng)賦為默認(rèn)值 nil
。
如果一個(gè)可選類型的實(shí)例包含一個(gè)值,那么你就可以使用后綴運(yùn)算符 !
來獲取該值,正如下面描述的:
optionalInteger = 42
optionalInteger! // 42
使用 !
運(yùn)算符解包值為 nil
的可選值會導(dǎo)致運(yùn)行錯(cuò)誤。
你也可以使用可選鏈?zhǔn)秸{(diào)用和可選綁定來選擇性地在可選表達(dá)式上執(zhí)行操作。如果值為 nil
,不會執(zhí)行任何操作,因此也就沒有運(yùn)行錯(cuò)誤產(chǎn)生。
更多細(xì)節(jié)以及更多如何使用可選類型的例子,請參閱 可選類型。
可選類型語法
可選類型 → 類型 ?
當(dāng)可以被訪問時(shí),Swift 語言定義后綴 !
作為標(biāo)準(zhǔn)庫中命名類型 Optional<Wrapped>
的語法糖,來實(shí)現(xiàn)自動(dòng)解包的功能。換句話說,下面兩個(gè)聲明等價(jià):
var implicitlyUnwrappedString: String!
var explicitlyUnwrappedString: Optional<String>
注意類型與 !
之間沒有空格。
由于隱式解包修改了包涵其類型的聲明語義,嵌套在元組類型或泛型的可選類型(比如字典元素類型或數(shù)組元素類型),不能被標(biāo)記為隱式解包。例如:
let tupleOfImplicitlyUnwrappedElements: (Int!, Int!) // 錯(cuò)誤
let implicitlyUnwrappedTuple: (Int, Int)! // 正確
let arrayOfImplicitlyUnwrappedElements: [Int!] // 錯(cuò)誤
let implicitlyUnwrappedArray: [Int]! // 正確
由于隱式解析可選類型和可選類型有同樣的表達(dá)式 Optional<Wrapped>
,你可以在使用可選類型的地方使用隱式解析可選類型。比如,你可以將隱式解析可選類型的值賦給變量、常量和可選屬性,反之亦然。
正如可選類型一樣,你在聲明隱式解析可選類型的變量或?qū)傩缘臅r(shí)候也不用指定初始值,因?yàn)樗心J(rèn)值 nil
。
可以使用可選鏈?zhǔn)秸{(diào)用來在隱式解析可選表達(dá)式上選擇性地執(zhí)行操作。如果值為 nil
,就不會執(zhí)行任何操作,因此也不會產(chǎn)生運(yùn)行錯(cuò)誤。
關(guān)于隱式解析可選類型的更多細(xì)節(jié),請參閱 隱式解析可選類型。
隱式解析可選類型語法
隱式解析可選類型 → 類型 !
協(xié)議合成類型是一種符合協(xié)議列表中每個(gè)指定協(xié)議的類型。協(xié)議合成類型可能會用在類型注解和泛型參數(shù)中。
協(xié)議合成類型的形式如下:
Protocol 1
&Procotol 2
協(xié)議合成類型允許你指定一個(gè)值,其類型符合多個(gè)協(xié)議的要求且不需要定義一個(gè)新的命名型協(xié)議來繼承它想要符合的各個(gè)協(xié)議。比如,協(xié)議合成類型 Protocol A & Protocol B & Protocol C
等效于一個(gè)從 Protocol A
,Protocol B
,Protocol C
繼承而來的新協(xié)議 Protocol D
,很顯然這樣做有效率的多,甚至不需引入一個(gè)新名字。
協(xié)議合成列表中的每項(xiàng)必須是協(xié)議名或協(xié)議合成類型的類型別名。
協(xié)議合成類型語法
協(xié)議合成類型 → 協(xié)議標(biāo)識符 & 協(xié)議合成延續(xù) 協(xié)議合成延續(xù) → 協(xié)議標(biāo)識符 | 協(xié)議合成類型 協(xié)議標(biāo)識符 → 類型標(biāo)識符
元類型是指類型的類型,包括類類型、結(jié)構(gòu)體類型、枚舉類型和協(xié)議類型。
類、結(jié)構(gòu)體或枚舉類型的元類型是相應(yīng)的類型名緊跟 .Type
。協(xié)議類型的元類型——并不是運(yùn)行時(shí)符合該協(xié)議的具體類型——而是該協(xié)議名字緊跟 .Protocol
。比如,類 SomeClass
的元類型就是 SomeClass.Type
,協(xié)議 SomeProtocol
的元類型就是 SomeProtocal.Protocol
。
你可以使用后綴 self
表達(dá)式來獲取類型。比如,SomeClass.self
返回 SomeClass
本身,而不是 SomeClass
的一個(gè)實(shí)例。同樣,SomeProtocol.self
返回 SomeProtocol
本身,而不是運(yùn)行時(shí)符合 SomeProtocol
的某個(gè)類型的實(shí)例。還可以對類型的實(shí)例使用 type(of:)
表達(dá)式來獲取該實(shí)例在運(yùn)行階段的類型,如下所示:
class SomeBaseClass {
class func printClassName() {
println("SomeBaseClass")
}
}
class SomeSubClass: SomeBaseClass {
override class func printClassName() {
println("SomeSubClass")
}
}
let someInstance: SomeBaseClass = SomeSubClass()
// someInstance 在編譯期是 SomeBaseClass 類型,
// 但是在運(yùn)行期則是 SomeSubClass 類型
type(of: someInstance).printClassName()
// 打印 “SomeSubClass”
更多信息可以查看 Swift 標(biāo)準(zhǔn)庫里的 type(of:)
。
可以使用初始化表達(dá)式從某個(gè)類型的元類型構(gòu)造出一個(gè)該類型的實(shí)例。對于類實(shí)例,被調(diào)用的構(gòu)造器必須使用 required
關(guān)鍵字標(biāo)記,或者整個(gè)類使用 final
關(guān)鍵字標(biāo)記。
class AnotherSubClass: SomeBaseClass {
let string: String
required init(string: String) {
self.string = string
}
override class func printClassName() {
print("AnotherSubClass")
}
}
let metatype: AnotherSubClass.Type = AnotherSubClass.self
let anotherInstance = metatype.init(string: "some string")
元類型語法
類型繼承子句被用來指定一個(gè)命名型類型繼承自哪個(gè)類、采納哪些協(xié)議。類型繼承子句也用來指定一個(gè)類類型專屬協(xié)議。類型繼承子句開始于冒號 :
,其后是所需要的類、類型標(biāo)識符列表或兩者都有。
類可以繼承單個(gè)超類,采納任意數(shù)量的協(xié)議。當(dāng)定義一個(gè)類時(shí),超類的名字必須出現(xiàn)在類型標(biāo)識符列表首位,然后跟上該類需要采納的任意數(shù)量的協(xié)議。如果一個(gè)類不是從其它類繼承而來,那么列表可以以協(xié)議開頭。關(guān)于類繼承更多的討論和例子,請參閱 繼承。
其它命名型類型可能只繼承或采納一系列協(xié)議。協(xié)議類型可以繼承自任意數(shù)量的其他協(xié)議。當(dāng)一個(gè)協(xié)議類型繼承自其它協(xié)議時(shí),其它協(xié)議中定義的要求會被整合在一起,然后從當(dāng)前協(xié)議繼承的任意類型必須符合所有這些條件。正如在 協(xié)議聲明 中所討論的那樣,可以把 class
關(guān)鍵字放到協(xié)議類型的類型繼承子句的首位,這樣就可以聲明一個(gè)類類型專屬協(xié)議。
枚舉定義中的類型繼承子句可以是一系列協(xié)議,或是枚舉的原始值類型的命名型類型。在枚舉定義中使用類型繼承子句來指定原始值類型的例子,請參閱 原始值。
類型繼承子句語法
類型繼承子句 → : 類型繼承列表 類型繼承列表 → 類型標(biāo)識符 | 類型標(biāo)識符 , 類型繼承列表
Swift 廣泛使用類型推斷,從而允許你省略代碼中很多變量和表達(dá)式的類型或部分類型。比如,對于 var x: Int = 0
,你可以完全省略類型而簡寫成 var x = 0
,編譯器會正確推斷出 x
的類型 Int
。類似的,當(dāng)完整的類型可以從上下文推斷出來時(shí),你也可以省略類型的一部分。比如,如果你寫了 let dict: Dictionary = ["A" : 1]
,編譯器能推斷出 dict
的類型是 Dictionary<String, Int>
。
在上面的兩個(gè)例子中,類型信息從表達(dá)式樹的葉子節(jié)點(diǎn)傳向根節(jié)點(diǎn)。也就是說,var x: Int = 0
中 x
的類型首先根據(jù) 0
的類型進(jìn)行推斷,然后將該類型信息傳遞到根節(jié)點(diǎn)(變量 x
)。
在 Swift 中,類型信息也可以反方向流動(dòng)——從根節(jié)點(diǎn)傳向葉子節(jié)點(diǎn)。在下面的例子中,常量 eFloat
上的顯式類型注解(: Float
)將導(dǎo)致數(shù)字字面量 2.71828
的類型是 Float
而非 Double
。
let e = 2.71828 // e 的類型會被推斷為 Double
let eFloat: Float = 2.71828 // eFloat 的類型為 Float
Swift 中的類型推斷在單獨(dú)的表達(dá)式或語句上進(jìn)行。這意味著所有用于類型推斷的信息必須可以從表達(dá)式或其某個(gè)子表達(dá)式的類型檢查中獲取到。