1.0 翻譯:marsprince Lenhoon(微博) 校對:numbbbbb, stanzhai
2.1 翻譯:mmoaay, shanks 校對:shanks
2.2 翻譯:星夜暮晨
3.0 翻譯:chenmingjia
本頁包含內(nèi)容:
聲明 (declaration) 用以向程序里引入新的名字或者結(jié)構(gòu)。舉例來說,可以使用聲明來引入函數(shù)和方法,變量和常量,或者定義新的具有命名的枚舉、結(jié)構(gòu)、類和協(xié)議類型。還可以使用聲明來擴展一個既有的具有命名的類型的行為,或者在程序里引入在其它地方聲明的符號。
在 Swift 中,大多數(shù)聲明在某種意義上講也是定義,因為聲明往往伴隨著實現(xiàn)或初始化。由于協(xié)議并不提供實現(xiàn),大多數(shù)協(xié)議成員僅僅只是聲明而已。為了方便起見,也是因為這些區(qū)別在 Swift 中并不是很重要,“聲明”這個術(shù)語同時包含了聲明和定義兩種含義。
聲明語法
</a> 聲明 → 導(dǎo)入聲明
聲明 → 常量聲明
聲明 → 變量聲明
聲明 → 類型別名聲明
聲明 → 函數(shù)聲明
聲明 → 枚舉聲明
聲明 → 結(jié)構(gòu)體聲明
聲明 → 類聲明
聲明 → 協(xié)議聲明
聲明 → 構(gòu)造器聲明
聲明 → 析構(gòu)器聲明
聲明 → 擴展聲明
聲明 → 下標(biāo)聲明
聲明 → 運算符聲明
多條聲明 → 聲明 多條聲明可選
Swift 的源文件中的頂級代碼 (top-level code) 由零個或多個語句、聲明和表達(dá)式組成。默認(rèn)情況下,在一個源文件的頂層聲明的變量,常量和其他具有命名的聲明可以被同模塊中的每一個源文件中的代碼訪問??梢允褂靡粋€訪問級別修飾符來標(biāo)記聲明來覆蓋這種默認(rèn)行為,請參閱 訪問控制級別。
頂級聲明語法
頂級聲明 → 多條語句可選
代碼塊 (code block) 可以將一些聲明和控制結(jié)構(gòu)組織在一起。它有如下的形式:
{
語句
}
代碼塊中的“語句”包括聲明、表達(dá)式和各種其他類型的語句,它們按照在源碼中的出現(xiàn)順序被依次執(zhí)行。
代碼塊語法
代碼塊 → { 多條語句可選 }
導(dǎo)入聲明 (import declaration) 讓你可以使用在其他文件中聲明的內(nèi)容。導(dǎo)入語句的基本形式是導(dǎo)入整個模塊,它由 import
關(guān)鍵字和緊隨其后的模塊名組成:
import 模塊
可以對導(dǎo)入操作提供更細(xì)致的控制,如指定一個特殊的子模塊或者指定一個模塊或子模塊中的某個聲明。提供了這些限制后,在當(dāng)前作用域中,只有被導(dǎo)入的符號是可用的,而不是整個模塊中的所有聲明。
import 導(dǎo)入類型 模塊.符號名
import 模塊.子模塊
導(dǎo)入聲明語法
</a> 導(dǎo)入聲明 → 特性列表可選 import 導(dǎo)入類型可選 導(dǎo)入路徑
導(dǎo)入類型 → typealias | struct | class | enum | protocol | var | func
</a> 導(dǎo)入路徑 → 導(dǎo)入路徑標(biāo)識符 | 導(dǎo)入路徑標(biāo)識符 . 導(dǎo)入路徑
導(dǎo)入路徑標(biāo)識符 → 標(biāo)識符 | 運算符
常量聲明 (constant declaration) 可以在程序中引入一個具有命名的常量。常量以關(guān)鍵字 let
來聲明,遵循如下格式:
let 常量名稱: 類型 = 表達(dá)式
常量聲明在“常量名稱”和用于初始化的“表達(dá)式”的值之間定義了一種不可變的綁定關(guān)系;當(dāng)常量的值被設(shè)定之后,它就無法被更改。這意味著,如果常量以類對象來初始化,對象本身的內(nèi)容是可以改變的,但是常量和該對象之間的綁定關(guān)系是不能改變的。
當(dāng)一個常量被聲明為全局常量時,它必須擁有一個初始值。在類或者結(jié)構(gòu)中聲明一個常量時,它將作為常量屬性 (constant property)。常量聲明不能是計算型屬性,因此也沒有存取方法。
如果常量名稱是元組形式,元組中每一項的名稱都會和初始化表達(dá)式中對應(yīng)的值進行綁定。
let (firstNumber, secondNumber) = (10, 42)
在上例中,firstNumber
是一個值為 10
的常量,secnodeName
是一個值為 42
的常量。所有常量都可以獨立地使用:
print("The first number is \(firstNumber).")
// 打印 “The first number is 10.”
print("The second number is \(secondNumber).")
// 打印 “The second number is 42.”
當(dāng)常量名稱的類型 (:
類型) 可以被推斷出時,類型標(biāo)注在常量聲明中是可選的,正如 類型推斷 中所描述的。
聲明一個常量類型屬性要使用 static
聲明修飾符。類型屬性在 類型屬性中有介紹。
如果還想獲得更多關(guān)于常量的信息或者想在使用中獲得幫助,請參閱 常量和變量 和 存儲屬性。
常量聲明語法
</a> 常量聲明 → 特性列表可選 聲明修飾符列表可選 let 模式構(gòu)造器列表
模式構(gòu)造器列表 → 模式構(gòu)造器 | 模式構(gòu)造器 , 模式構(gòu)造器列表
</a> 模式構(gòu)造器 → 模式 構(gòu)造器可選
構(gòu)造器 → = 表達(dá)式
變量聲明 (variable declaration) 可以在程序中引入一個具有命名的變量,它以關(guān)鍵字 var
來聲明。
變量聲明有幾種不同的形式,可以聲明不同種類的命名值和可變值,如存儲型和計算型變量和屬性,屬性觀察器,以及靜態(tài)變量屬性。所使用的聲明形式取決于變量聲明的適用范圍和打算聲明的變量類型。
注意
也可以在協(xié)議聲明中聲明屬性,詳情請參閱 協(xié)議屬性聲明。
可以在子類中重寫繼承來的變量屬性,使用 override
聲明修飾符標(biāo)記屬性的聲明即可,詳情請參閱 重寫。
使用如下形式聲明一個存儲型變量或存儲型變量屬性:
var 變量名稱: 類型 = 表達(dá)式
可以在全局范圍,函數(shù)內(nèi)部,或者在類和結(jié)構(gòu)的聲明中使用這種形式來聲明一個變量。當(dāng)變量以這種形式在全局范圍或者函數(shù)內(nèi)部被聲明時,它代表一個存儲型變量。當(dāng)它在類或者結(jié)構(gòu)中被聲明時,它代表一個存儲型變量屬性 (stored variable property)。
用于初始化的表達(dá)式不可以在協(xié)議的聲明中出現(xiàn),在其他情況下,該表達(dá)式是可選的。如果沒有初始化表達(dá)式,那么變量聲明必須包含類型標(biāo)注 (:
type)。
如同常量聲明,如果變量名稱是元組形式,元組中每一項的名稱都會和初始化表達(dá)式中對應(yīng)的值進行綁定。
正如名字所示,存儲型變量和存儲型變量屬性的值會存儲在內(nèi)存中。
使用如下形式聲明一個計算型變量或計算型屬性:
var 變量名稱: 類型 {
get {
語句
}
set(setter 名稱) {
語句
}
}
可以在全局范圍、函數(shù)內(nèi)部,以及類、結(jié)構(gòu)、枚舉、擴展的聲明中使用這種形式的聲明。當(dāng)變量以這種形式在全局范圍或者函數(shù)內(nèi)部被聲明時,它表示一個計算型變量。當(dāng)它在類、結(jié)構(gòu)、枚舉、擴展聲明的上下文中被聲明時,它表示一個計算型屬性 (computed property)。
getter 用來讀取變量值,setter 用來寫入變量值。setter 子句是可選的,getter 子句是必須的。不過也可以將這些子句都省略,直接返回請求的值,正如在 只讀計算型屬性 中描述的那樣。但是如果提供了一個 setter 子句,就必須也提供一個 getter 子句。
setter 的圓括號以及 setter 名稱是可選的。如果提供了 setter 名稱,它就會作為 setter 的參數(shù)名稱使用。如果不提供 setter 名稱,setter 的參數(shù)的默認(rèn)名稱為 newValue
,正如在 便捷 setter 聲明 中描述的那樣。
與存儲型變量和存儲型屬性不同,計算型變量和計算型屬性的值不存儲在內(nèi)存中。
要獲得更多關(guān)于計算型屬性的信息和例子,請參閱 計算型屬性。
可以在聲明存儲型變量或?qū)傩詴r提供 willSet
和 didSet
觀察器。一個包含觀察器的存儲型變量或?qū)傩砸匀缦滦问铰暶鳎?/p>
var 變量名稱: 類型 = 表達(dá)式 {
willSet(setter 名稱) {
語句
}
didSet(setter 名稱) {
語句
}
}
可以在全局范圍、函數(shù)內(nèi)部,或者類、結(jié)構(gòu)的聲明中使用這種形式的聲明。當(dāng)變量以這種形式在全局范圍或者函數(shù)內(nèi)部被聲明時,觀察器表示一個存儲型變量觀察器。當(dāng)它在類和結(jié)構(gòu)的聲明中被聲明時,觀察器表示一個屬性觀察器。
可以為任何存儲型屬性添加觀察器。也可以通過重寫父類屬性的方式為任何繼承的屬性(無論是存儲型還是計算型的)添加觀察器 ,正如 重寫屬性觀察器 中所描述的。
用于初始化的表達(dá)式在類或者結(jié)構(gòu)的聲明中是可選的,但是在其他聲明中則是必須的。如果可以從初始化表達(dá)式中推斷出類型信息,那么可以不提供類型標(biāo)注。
當(dāng)變量或?qū)傩缘闹当桓淖儠r,willSet
和 didSet
觀察器提供了一種觀察方法。觀察器會在變量的值被改變時調(diào)用,但不會在初始化時被調(diào)用。
willSet
觀察器只在變量或?qū)傩缘闹当桓淖冎罢{(diào)用。新的值作為一個常量傳入 willSet
觀察器,因此不可以在 willSet
中改變它。didSet
觀察器在變量或?qū)傩缘闹当桓淖兒罅⒓凑{(diào)用。和 willSet
觀察器相反,為了方便獲取舊值,舊值會傳入 didSet
觀察器。這意味著,如果在變量或?qū)傩缘?didiset
觀察器中設(shè)置值,設(shè)置的新值會取代剛剛在 willSet
觀察器中傳入的那個值。
在 willSet
和 didSet
中,圓括號以及其中的 setter 名稱是可選的。如果提供了一個 setter 名稱,它就會作為 willSet
和 didSet
的參數(shù)被使用。如果不提供 setter 名稱,willSet
觀察器的默認(rèn)參數(shù)名為 newValue
,didSet
觀察器的默認(rèn)參數(shù)名為 oldValue
。
提供了 willSet
時,didSet
是可選的。同樣的,提供了 didSet
時,willSet
則是可選的。
要獲得更多信息以及查看如何使用屬性觀察器的例子,請參閱 屬性觀察器。
要聲明一個類型變量屬性,用 static
聲明修飾符標(biāo)記該聲明。類可以改用 class
聲明修飾符標(biāo)記類的類型計算型屬性從而允許子類重寫超類的實現(xiàn)。類型屬性在 類型屬性 章節(jié)有詳細(xì)討論。
注意
在一個類聲明中,使用關(guān)鍵字static
與同時使用class
和final
去標(biāo)記一個聲明的效果相同。
變量聲明語法
變量聲明 → 變量聲明頭 模式構(gòu)造器列表
變量聲明 → 變量聲明頭 變量名稱 類型標(biāo)注 代碼塊
變量聲明 → 變量聲明頭 變量名稱 類型標(biāo)注 getter-setter代碼塊
變量聲明 → 變量聲明頭 變量名稱 類型標(biāo)注 getter-setter關(guān)鍵字代碼塊
變量聲明 → 變量聲明頭 變量名稱 構(gòu)造器 willSet-didSet代碼塊
變量聲明 → 變量聲明頭 變量名稱 類型標(biāo)注 構(gòu)造器可選 willSet-didSet代碼塊
getter-setter 代碼塊 → 代碼塊
getter-setter 代碼塊 → { getter子句 setter子句可選 }
getter-setter 代碼塊 → { setter子句 getter子句 }
</a> getter 子句 → 特性列表可選 get 代碼塊
setter 子句 → 特性列表可選 set setter名稱可選 代碼塊
setter 名稱 → ( 標(biāo)識符 )
getter-setter 關(guān)鍵字代碼塊 → { getter關(guān)鍵字子句 setter關(guān)鍵字子句可選 }
getter-setter 關(guān)鍵字代碼塊 → { setter關(guān)鍵字子句 getter關(guān)鍵字子句 }
</a> getter 關(guān)鍵字子句 → 特性列表可選 get
setter 關(guān)鍵字子句 → 特性列表可選 set
willSet-didSet 代碼塊 → { willSet子句 didSet子句可選 }
willSet-didSet 代碼塊 → { didSet子句 willSet子句可選 }
</a> willSet 子句 → 特性列表可選 willSet setter名稱可選 代碼塊
didSet 子句 → 特性列表可選 didSet setter名稱可選 代碼塊
類型別名 (type alias) 聲明可以在程序中為一個既有類型聲明一個別名。類型別名聲明語句使用關(guān)鍵字 typealias
聲明,遵循如下的形式:
typealias 類型別名 = 現(xiàn)存類型
當(dāng)聲明一個類型的別名后,可以在程序的任何地方使用“別名”來代替現(xiàn)有類型?,F(xiàn)有類型可以是具有命名的類型或者混合類型。類型別名不產(chǎn)生新的類型,它只是使用別名來引用現(xiàn)有類型。 類型別名聲明可以通過泛型參數(shù)來給一個現(xiàn)有泛型類型提供名稱。類型別名為現(xiàn)有類型的一部分或者全部泛型參數(shù)提供具體類型。例如:
typealias StringDictionary<Value> = Dictionary<String, Value>
// 下列兩個字典擁有同樣的類型
var dictionary1: StringDictionary<Int> = [:]
var dictionary2: Dictionary<String, Int> = [:]
當(dāng)一個類型別名帶著泛型參數(shù)一起被聲明時,這些參數(shù)的約束必須與現(xiàn)有參數(shù)的約束完全匹配。例如:
typealias DictionaryOfInts<Key: Hashable> = Dictionary<Key, Int>
因為類型別名可以和現(xiàn)有類型相互交換使用,類型別名不可以引入額外的類型約束。 在協(xié)議聲明中,類型別名可以為那些經(jīng)常使用的類型提供一個更短更方便的名稱,例如:
protocol Sequence {
associatedtype Iterator: IteratorProtocol
typealias Element = Iterator.Element
}
func sum<T: Sequence>(_ sequence: T) -> Int where T.Element == Int {
// ...
}
假如沒有類型別名,sum函數(shù)將必須引用關(guān)聯(lián)類型通過T.Iterator.Element的形式來替代 T.Element。
另請參閱 協(xié)議關(guān)聯(lián)類型聲明。
類型別名聲明語法
</a> 類型別名聲明 → 類型別名頭 類型別名賦值
類型別名頭 → 特性列表可選 訪問級別修飾符可選 typealias 類型別名名稱
</a> 類型別名名稱 → 標(biāo)識符
類型別名賦值 → = 類型
使用函數(shù)聲明 (function declaration) 在程序中引入新的函數(shù)或者方法。在類、結(jié)構(gòu)體、枚舉,或者協(xié)議中聲明的函數(shù)會作為方法。函數(shù)聲明使用關(guān)鍵字 func
,遵循如下的形式:
func 函數(shù)名稱(參數(shù)列表) -> 返回類型 {
語句
}
如果函數(shù)返回 Void
類型,返回類型可以省略,如下所示:
func 函數(shù)名稱(參數(shù)列表) {
語句
}
每個參數(shù)的類型都要標(biāo)明,因為它們不能被推斷出來。如果您在某個參數(shù)類型前面加上了 inout
,那么這個參數(shù)就可以在這個函數(shù)作用域當(dāng)中被修改。更多關(guān)于 inout
參數(shù)的討論,請參閱 輸入輸出參數(shù)。
函數(shù)可以使用元組類型作為返回類型來返回多個值。
函數(shù)定義可以出現(xiàn)在另一個函數(shù)聲明內(nèi)。這種函數(shù)被稱作嵌套函數(shù) (nested function)。更多關(guān)于嵌套函數(shù)的討論,請參閱 嵌套函數(shù)。
函數(shù)的參數(shù)列表由一個或多個函數(shù)參數(shù)組成,參數(shù)間以逗號分隔。函數(shù)調(diào)用時的參數(shù)順序必須和函數(shù)聲明時的參數(shù)順序一致。最簡單的參數(shù)列表有著如下的形式:
參數(shù)名稱
: 參數(shù)類型
一個參數(shù)有一個內(nèi)部名稱,這個內(nèi)部名稱可以在函數(shù)體內(nèi)被使用。還有一個外部名稱,當(dāng)調(diào)用函數(shù)時這個外部名稱被作為實參的標(biāo)簽來使用。默認(rèn)情況下,第一個參數(shù)的外部名稱會被省略,第二個和之后的參數(shù)使用它們的內(nèi)部名稱作為它們的外部名稱。例如:
func f(x: Int, y: Int) -> Int { return x + y }
f(1, y: 2) // 參數(shù) y 有標(biāo)簽,參數(shù) x 則沒有
可以按照如下兩種形式之一,重寫參數(shù)名稱的默認(rèn)行為:
外部參數(shù)名稱
內(nèi)部參數(shù)名稱
: 參數(shù)類型
_ 內(nèi)部參數(shù)名稱
: 參數(shù)類型
在內(nèi)部參數(shù)名稱前的名稱會作為這個參數(shù)的外部名稱,這個名稱可以和內(nèi)部參數(shù)的名稱不同。外部參數(shù)名稱在函數(shù)被調(diào)用時必須被使用,即對應(yīng)的參數(shù)在方法或函數(shù)被調(diào)用時必須有外部名。
內(nèi)部參數(shù)名稱前的下劃線(_
)可使該參數(shù)在函數(shù)被調(diào)用時沒有名稱。在函數(shù)或方法調(diào)用時,對應(yīng)的參數(shù)必須沒有名字。
func f(x x: Int, withY y: Int, _ z: Int) -> Int { return x + y + z }
f(x: 1, withY: 2, 3) // 參數(shù) x 和 y 是有標(biāo)簽的,參數(shù) z 則沒有
輸入輸出參數(shù)被傳遞時遵循如下規(guī)則:
這種行為被稱為拷入拷出 (copy-in copy-out) 或值結(jié)果調(diào)用 (call by value result)。例如,當(dāng)一個計算型屬性或者一個具有屬性觀察器的屬性被用作函數(shù)的輸入輸出參數(shù)時,其 getter 會在函數(shù)調(diào)用時被調(diào)用,而其 setter 會在函數(shù)返回時被調(diào)用。
作為一種優(yōu)化手段,當(dāng)參數(shù)值存儲在內(nèi)存中的物理地址時,在函數(shù)體內(nèi)部和外部均會使用同一內(nèi)存位置。這種優(yōu)化行為被稱為引用調(diào)用 (call by reference),它滿足了拷入拷出模式的所有要求,且消除了復(fù)制帶來的開銷。在代碼中,要規(guī)范使用拷入拷出模式,不要依賴于引用調(diào)用。
不要使用傳遞給輸入輸出參數(shù)的值,即使原始值在當(dāng)前作用域中依然可用。當(dāng)函數(shù)返回時,你對原始值所做的更改會被拷貝的值所覆蓋。不要依賴于引用調(diào)用的優(yōu)化機制來試圖避免這種覆蓋。
不能將同一個值傳遞給多個輸入輸出參數(shù),因為這種情況下的拷貝與覆蓋行為的順序是不確定的,因此原始值的最終值也將無法確定。例如:
var x = 10
func f(inout a: Int, inout _ b: Int) {
a += 1
b += 10
}
f(&x, &x) // 編譯報錯 error: inout arguments are not allowed to alias each other
如果嵌套函數(shù)在外層函數(shù)返回后才調(diào)用,嵌套函數(shù)對輸入輸出參數(shù)造成的任何改變將不會影響到原始值。例如:
func outer(inout a: Int) -> () -> Void {
func inner() {
a += 1
}
return inner
}
var x = 10
let f = outer(&x)
f()
print(x)
// 打印 “10”
調(diào)用嵌套函數(shù) inner()
對 a
遞增后,x
的值并未發(fā)生改變,因為 inner()
在外層函數(shù) outer()
返回后才被調(diào)用。若要改變 x
的值,必須在 outer()
返回前調(diào)用 inner()
。
關(guān)于輸入輸出參數(shù)的詳細(xì)討論,請參閱 輸入輸出參數(shù)。
參數(shù)可以被忽略,數(shù)量可以不固定,還可以為其提供默認(rèn)值,使用形式如下:
_ : 參數(shù)類型
參數(shù)名稱: 參數(shù)類型...
參數(shù)名稱: 參數(shù)類型 = 默認(rèn)參數(shù)值
以下劃線(_
)命名的參數(shù)會被顯式忽略,無法在函數(shù)體內(nèi)使用。
一個參數(shù)的基本類型名稱如果緊跟著三個點(...
),會被視為可變參數(shù)。一個函數(shù)至多可以擁有一個可變參數(shù),且必須是最后一個參數(shù)。可變參數(shù)會作為包含該參數(shù)類型元素的數(shù)組處理。舉例來講,可變參數(shù) Int...
會作為 [Int]
來處理。關(guān)于使用可變參數(shù)的例子,請參閱 可變參數(shù)。
如果在參數(shù)類型后面有一個以等號(=
)連接的表達(dá)式,該參數(shù)會擁有默認(rèn)值,即給定表達(dá)式的值。當(dāng)函數(shù)被調(diào)用時,給定的表達(dá)式會被求值。如果參數(shù)在函數(shù)調(diào)用時被省略了,就會使用其默認(rèn)值。
func f(x: Int = 42) -> Int { return x }
f() // 有效,使用默認(rèn)值
f(7) // 有效,提供了值
f(x: 7) // 無效,該參數(shù)沒有外部名稱
枚舉或結(jié)構(gòu)體的方法如果會修改 self
,則必須以 mutating
聲明修飾符標(biāo)記。
子類重寫超類中的方法必須以 override
聲明修飾符標(biāo)記。重寫方法時不使用 override
修飾符,或者被 override
修飾符修飾的方法并未對超類方法構(gòu)成重寫,都會導(dǎo)致編譯錯誤。
枚舉或者結(jié)構(gòu)體中的類型方法,要以 static
聲明修飾符標(biāo)記,而對于類中的類型方法,除了使用 static
,還可使用 class
聲明修飾符標(biāo)記。
可以拋出錯誤的函數(shù)或方法必須使用 throws
關(guān)鍵字標(biāo)記。這類函數(shù)和方法被稱為拋出函數(shù)和拋出方法。它們有著下面的形式:
func 函數(shù)名稱(參數(shù)列表) throws -> 返回類型 {
語句
}
拋出函數(shù)或拋出方法的調(diào)用必須包裹在 try
或者 try!
表達(dá)式中(也就是說,在作用域內(nèi)使用 try
或者 try!
運算符)。
throws
關(guān)鍵字是函數(shù)的類型的一部分,非拋出函數(shù)是拋出函數(shù)的子類型。所以,可以在使用拋出函數(shù)的地方使用非拋出函數(shù)。
不能僅基于函數(shù)能否拋出錯誤來進行函數(shù)重載。也就是說,可以基于函數(shù)的函數(shù)類型的參數(shù)能否拋出錯誤來進行函數(shù)重載。
拋出方法不能重寫非拋出方法,而且拋出方法不能滿足協(xié)議對于非拋出方法的要求。也就是說,非拋出方法可以重寫拋出方法,而且非拋出方法可以滿足協(xié)議對于拋出方法的要求。
函數(shù)或方法可以使用 rethrows
關(guān)鍵字來聲明,從而表明僅當(dāng)該函數(shù)或方法的一個函數(shù)類型的參數(shù)拋出錯誤時,該函數(shù)或方法才拋出錯誤。這類函數(shù)和方法被稱為重拋函數(shù)和重拋方法。重新拋出錯誤的函數(shù)或方法必須至少有一個參數(shù)的類型為拋出函數(shù)。
func someFunction(callback: () throws -> Void) rethrows {
try callback()
}
重拋函數(shù)或者方法不能夠從自身直接拋出任何錯誤,這意味著它不能夠包含 throw
語句。它只能夠傳遞作為參數(shù)的拋出函數(shù)所拋出的錯誤。例如,在 do-catch
代碼塊中調(diào)用拋出函數(shù),并在 catch
子句中拋出其它錯誤都是不允許的。
拋出方法不能重寫重拋方法,而且拋出方法不能滿足協(xié)議對于重拋方法的要求。也就是說,重拋方法可以重寫拋出方法,而且重拋方法可以滿足協(xié)議對于拋出方法的要求。
Swift定義了Never
類型,它表示函數(shù)或者方法不會返回給它的調(diào)用者。Never
返回類型的函數(shù)或方法可以稱為不歸,不歸函數(shù)、方法要么引發(fā)不可恢復(fù)的錯誤,要么永遠(yuǎn)不停地運作,這會使調(diào)用后本應(yīng)執(zhí)行得代碼就不再執(zhí)行了。但即使是不歸函數(shù)、方法,拋錯函數(shù)和重拋出函數(shù)也可以將程序控制轉(zhuǎn)移到合適的catch
代碼塊。
不歸函數(shù)、方法可以在guard語句的else字句中調(diào)用,具體討論在Guard語句。
你可以重載一個不歸方法,但是新的方法必須保持原有的返回類型和沒有返回的行為。
函數(shù)聲明語法
函數(shù)簽名 → 參數(shù)子句列表 throws可選 函數(shù)結(jié)果可選
函數(shù)簽名 → 參數(shù)子句列表 rethrows 函數(shù)結(jié)果可選
</a> 函數(shù)結(jié)果 → -> 特性列表可選 類型
函數(shù)體 → 代碼塊
參數(shù)子句列表 → 參數(shù)子句 參數(shù)子句列表可選
</a> 參數(shù)子句 → ( ) | ( 參數(shù)列表 )
參數(shù)列表 → 參數(shù) | 參數(shù) , 參數(shù)列表
</a> 參數(shù) → let可選 外部參數(shù)名可選 內(nèi)部參數(shù)名 類型標(biāo)注 默認(rèn)參數(shù)子句可選
參數(shù) → inout 外部參數(shù)名可選 內(nèi)部參數(shù)名 類型標(biāo)注
參數(shù) → 外部參數(shù)名可選 內(nèi)部參數(shù)名 類型標(biāo)注 ...
外部參數(shù)名 → 標(biāo)識符 | _
</a> 內(nèi)部參數(shù)名 → 標(biāo)識符 | _
默認(rèn)參數(shù)子句 → = 表達(dá)式
在程序中使用枚舉聲明 (enumeration declaration) 來引入一個枚舉類型。
枚舉聲明有兩種基本形式,使用關(guān)鍵字 enum
來聲明。枚舉聲明體包含零個或多個值,稱為枚舉用例,還可包含任意數(shù)量的聲明,包括計算型屬性、實例方法、類型方法、構(gòu)造器、類型別名,甚至其他枚舉、結(jié)構(gòu)體和類。枚舉聲明不能包含析構(gòu)器或者協(xié)議聲明。
枚舉類型可以采納任意數(shù)量的協(xié)議,但是枚舉不能從類、結(jié)構(gòu)體和其他枚舉繼承。
不同于類或者結(jié)構(gòu)體,枚舉類型并不隱式提供默認(rèn)構(gòu)造器,所有構(gòu)造器必須顯式聲明。一個構(gòu)造器可以委托給枚舉中的其他構(gòu)造器,但是構(gòu)造過程僅當(dāng)構(gòu)造器將一個枚舉用例賦值給 self
后才算完成。
和結(jié)構(gòu)體類似但是和類不同,枚舉是值類型。枚舉實例在被賦值到變量或常量時,或者傳遞給函數(shù)作為參數(shù)時會被復(fù)制。更多關(guān)于值類型的信息,請參閱 結(jié)構(gòu)體和枚舉是值類型。
可以擴展枚舉類型,正如在 擴展聲明 中討論的一樣。
如下的形式聲明了一個包含任意類型枚舉用例的枚舉變量:
enum 枚舉名稱: 采納的協(xié)議 {
case 枚舉用例1
case 枚舉用例2(關(guān)聯(lián)值類型)
}
這種形式的枚舉聲明在其他語言中有時被叫做可識別聯(lián)合。
在這種形式中,每個用例塊由關(guān)鍵字 case
開始,后面緊接一個或多個以逗號分隔的枚舉用例。每個用例名必須是獨一無二的。每個用例也可以指定它所存儲的指定類型的值,這些類型在關(guān)聯(lián)值類型的元組中被指定,緊跟用例名之后。
具有關(guān)聯(lián)值的枚舉用例可以像函數(shù)一樣使用,通過指定的關(guān)聯(lián)值創(chuàng)建枚舉實例。和真正的函數(shù)一樣,你可以獲取枚舉用例的引用,然后在后續(xù)代碼中調(diào)用它。
enum Number {
case Integer(Int)
case Real(Double)
}
// f 的類型為 (Int) -> Number
let f = Number.Integer
// 利用 f 把一個整數(shù)數(shù)組轉(zhuǎn)成 Number 數(shù)組
let evenInts: [Number] = [0, 2, 4, 6].map(f)
要獲得更多關(guān)于具有關(guān)聯(lián)值的枚舉用例的信息和例子,請參閱 關(guān)聯(lián)值。
枚舉類型可以具有遞歸結(jié)構(gòu),就是說,枚舉用例的關(guān)聯(lián)值類型可以是枚舉類型自身。然而,枚舉類型的實例具有值語義,這意味著它們在內(nèi)存中有固定布局。為了支持遞歸,編譯器必須插入一個間接層。
要讓某個枚舉用例支持遞歸,使用 indirect
聲明修飾符標(biāo)記該用例。
enum Tree<T> {
case Empty
indirect case Node(value: T, left: Tree, right:Tree)
}
要讓一個枚舉類型的所有用例都支持遞歸,使用 indirect
修飾符標(biāo)記整個枚舉類型,當(dāng)枚舉有多個用例且每個用例都需要使用 indirect
修飾符標(biāo)記的時候這將非常便利。
被 indirect
修飾符標(biāo)記的枚舉用例必須有一個關(guān)聯(lián)值。使用 indirect
修飾符標(biāo)記的枚舉類型可以既包含有關(guān)聯(lián)值的用例,同時還可包含沒有關(guān)聯(lián)值的用例。但是,它不能再單獨使用 indirect
修飾符來標(biāo)記某個用例。
以下形式聲明了一種枚舉類型,其中各個枚舉用例的類型均為同一種基本類型:
enum 枚舉名稱: 原始值類型, 采納的協(xié)議 {
case 枚舉用例1 = 原始值1
case 枚舉用例2 = 原始值2
}
在這種形式中,每一個用例塊由 case
關(guān)鍵字開始,后面緊跟一個或多個以逗號分隔的枚舉用例。和第一種形式的枚舉用例不同,這種形式的枚舉用例包含一個基礎(chǔ)值,叫做原始值,各個枚舉用例的原始值的類型必須相同。這些原始值的類型通過原始值類型指定,必須表示一個整數(shù)、浮點數(shù)、字符串或者字符。原始值類型必須符合 Equatable
協(xié)議和下列字面量轉(zhuǎn)換協(xié)議中的一種:整型字面量需符合 IntergerLiteralConvertible
協(xié)議,浮點型字面量需符合 FloatingPointLiteralConvertible
協(xié)議,包含任意數(shù)量字符的字符串型字面量需符合 StringLiteralConvertible
協(xié)議,僅包含一個單一字符的字符串型字面量需符合 ExtendedGraphemeClusterLiteralConvertible
協(xié)議。每一個用例的名字和原始值必須唯一。
如果原始值類型被指定為 Int
,則不必為用例顯式地指定原始值,它們會隱式地被賦值 0
、1
、2
等。每個未被賦值的 Int
類型的用例會被隱式地賦值,其值為上一個用例的原始值加 1
。
enum ExampleEnum: Int {
case A, B, C = 5, D
}
在上面的例子中,ExampleEnum.A
的原始值是 0
,ExampleEnum.B
的原始值是 1
。因為 ExampleEnum.C
的原始值被顯式地設(shè)定為 5
,因此 ExampleEnum.D
的原始值會自動增長為 6
。
如果原始值類型被指定為 String
類型,你不用明確地為用例指定原始值,每個沒有指定原始值的用例會隱式地將用例名字作為原始值。
enum WeekendDay: String {
case Saturday, Sunday
}
在上面這個例子中,WeekendDay.Saturday
的原始值是 "Saturday"
,WeekendDay.Sunday
的原始值是 "Sunday"
。
枚舉用例具有原始值的枚舉類型隱式地符合定義在 Swift 標(biāo)準(zhǔn)庫中的 RawRepresentable
協(xié)議。所以,它們擁有一個 rawValue
屬性和一個可失敗構(gòu)造器 init?(rawValue: RawValue)
??梢允褂?rawValue
屬性去獲取枚舉用例的原始值,例如 ExampleEnum.B.rawValue
。還可以根據(jù)原始值來創(chuàng)建一個相對應(yīng)的枚舉用例,只需調(diào)用枚舉的可失敗構(gòu)造器,例如 ExampleEnum(rawValue: 5)
,這個可失敗構(gòu)造器返回一個可選類型的用例。要獲得更多關(guān)于具有原始值的枚舉用例的信息和例子,請參閱 原始值。
使用點語法(.
)來引用枚舉類型的枚舉用例,例如 EnumerationType.EnumerationCase
。當(dāng)枚舉類型可以由上下文推斷而出時,可以省略它(但是 .
仍然需要),正如 枚舉語法 和 顯式成員表達(dá)式 所述。
可以使用 switch
語句來檢驗枚舉用例的值,正如 使用 switch 語句匹配枚舉值 所述。枚舉類型是模式匹配的,依靠 switch
語句 case
塊中的枚舉用例模式,正如 枚舉用例模式 所述。
枚舉聲明語法
枚舉聲明 → 特性列表可選 訪問級別修飾符可選 聯(lián)合風(fēng)格枚舉
枚舉聲明 → 特性列表可選 訪問級別修飾符 可選 原始值風(fēng)格枚舉
聯(lián)合風(fēng)格枚舉 → indirect可選 enum 枚舉名稱 泛型形參子句可選 類型繼承子句可選 { 多個聯(lián)合風(fēng)格枚舉成員可選 }
</a> 多個聯(lián)合風(fēng)格枚舉成員 → 聯(lián)合風(fēng)格枚舉成員 多個聯(lián)合風(fēng)格枚舉成員可選
聯(lián)合風(fēng)格枚舉成員 → 聲明 | 聯(lián)合風(fēng)格枚舉用例子句
</a> 聯(lián)合風(fēng)格枚舉用例子句 → 特性列表可選 indirect可選 case 聯(lián)合風(fēng)格枚舉用例列表
聯(lián)合風(fēng)格枚舉用例列表 → 聯(lián)合風(fēng)格枚舉用例 | 聯(lián)合風(fēng)格枚舉用例 , 聯(lián)合風(fēng)格枚舉用例列表
</a> 聯(lián)合風(fēng)格枚舉用例 → 枚舉用例名稱 元組類型可選
枚舉名稱 → 標(biāo)識符
枚舉用例名稱 → 標(biāo)識符
原始值風(fēng)格枚舉 → enum 枚舉名稱 泛型形參子句可選 類型繼承子句 { 多個原始值風(fēng)格枚舉成員 }
</a> 多個原始值風(fēng)格枚舉成員 → 原始值風(fēng)格枚舉成員 多個原始值風(fēng)格枚舉成員可選
原始值風(fēng)格枚舉成員 → 聲明 | 原始值風(fēng)格枚舉用例子句
</a> 原始值風(fēng)格枚舉用例子句 → 特性列表可選 case 原始值風(fēng)格枚舉用例列表
原始值風(fēng)格枚舉用例列表 → 原始值風(fēng)格枚舉用例 | 原始值風(fēng)格枚舉用例 , 原始值風(fēng)格枚舉用例列表
</a> 原始值風(fēng)格枚舉用例 → 枚舉用例名稱 原始值賦值可選
原始值賦值 → = 原始值字面量
原始值字面量 → 數(shù)字型字面量 | 字符串型字面量 | 布爾型字面量
使用結(jié)構(gòu)體聲明 (structure declaration) 可以在程序中引入一個結(jié)構(gòu)體類型。結(jié)構(gòu)體聲明使用 struct
關(guān)鍵字,遵循如下的形式:
struct 結(jié)構(gòu)體名稱: 采納的協(xié)議 {
多條聲明
}
結(jié)構(gòu)體內(nèi)可包含零個或多個聲明。這些聲明可以包括存儲型和計算型屬性、類型屬性、實例方法、類型方法、構(gòu)造器、下標(biāo)、類型別名,甚至其他結(jié)構(gòu)體、類、和枚舉聲明。結(jié)構(gòu)體聲明不能包含析構(gòu)器或者協(xié)議聲明。關(guān)于結(jié)構(gòu)體的詳細(xì)討論和示例,請參閱 類和結(jié)構(gòu)體。
結(jié)構(gòu)體可以采納任意數(shù)量的協(xié)議,但是不能繼承自類、枚舉或者其他結(jié)構(gòu)體。
有三種方法可以創(chuàng)建一個已聲明的結(jié)構(gòu)體實例:
調(diào)用結(jié)構(gòu)體內(nèi)聲明的構(gòu)造器,正如 構(gòu)造器 所述。
如果沒有聲明構(gòu)造器,調(diào)用結(jié)構(gòu)體的成員逐一構(gòu)造器,正如 結(jié)構(gòu)體類型的成員逐一構(gòu)造器 所述。
如果沒有聲明構(gòu)造器,而且結(jié)構(gòu)體的所有屬性都有初始值,調(diào)用結(jié)構(gòu)體的默認(rèn)構(gòu)造器,正如 默認(rèn)構(gòu)造器 所述。
結(jié)構(gòu)體的構(gòu)造過程請參閱 構(gòu)造過程。
結(jié)構(gòu)體實例的屬性可以用點語法(.
)來訪問,正如 訪問屬性 所述。
結(jié)構(gòu)體是值類型。結(jié)構(gòu)體的實例在被賦予變量或常量,或傳遞給函數(shù)作為參數(shù)時會被復(fù)制。關(guān)于值類型的更多信息,請參閱 結(jié)構(gòu)體和枚舉是值類型。
可以使用擴展聲明來擴展結(jié)構(gòu)體類型的行為,請參閱 擴展聲明。
結(jié)構(gòu)體聲明語法
</a> 結(jié)構(gòu)體聲明 → 特性列表可選 訪問級別修飾符 可選 struct 結(jié)構(gòu)體名稱 泛型形參子句可選 類型繼承子句可選 結(jié)構(gòu)體主體
結(jié)構(gòu)體名稱 → 標(biāo)識符
結(jié)構(gòu)體主體 → { 多條聲明可選 }
可以在程序中使用類聲明 (class declaration) 來引入一個類。類聲明使用關(guān)鍵字 class
,遵循如下的形式:
class 類名: 超類, 采納的協(xié)議 {
多條聲明
}
類內(nèi)可以包含零個或多個聲明。這些聲明可以包括存儲型和計算型屬性、實例方法、類型方法、構(gòu)造器、唯一的析構(gòu)器、下標(biāo)、類型別名,甚至其他結(jié)構(gòu)體、類和枚舉聲明。類聲明不能包含協(xié)議聲明。關(guān)于類的詳細(xì)討論和示例,請參閱 類和結(jié)構(gòu)體。
一個類只能繼承自一個超類,但是可以采納任意數(shù)量的協(xié)議。超類緊跟在類名和冒號后面,其后跟著采納的協(xié)議。泛型類可以繼承自其它泛型類和非泛型類,但是非泛型類只能繼承自其它非泛型類。當(dāng)在冒號后面寫泛型超類的名稱時,必須寫上泛型類的全名,包括它的泛型形參子句。
正如 構(gòu)造器聲明 所討論的,類可以有指定構(gòu)造器和便利構(gòu)造器。類的指定構(gòu)造器必須初始化類中聲明的所有屬性,并且必須在調(diào)用超類構(gòu)造器之前。
類可以重寫屬性、方法、下標(biāo)以及構(gòu)造器。重寫的屬性、方法、下標(biāo)和指定構(gòu)造器必須以 override
聲明修飾符標(biāo)記。
為了要求子類去實現(xiàn)超類的構(gòu)造器,使用 required
聲明修飾符標(biāo)記超類的構(gòu)造器。子類實現(xiàn)超類構(gòu)造器時也必須使用 required
聲明修飾符。
雖然超類屬性和方法聲明可以被當(dāng)前類繼承,但是超類聲明的指定構(gòu)造器卻不能。即便如此,如果當(dāng)前類重寫了超類的所有指定構(gòu)造器,它就會繼承超類的所有便利構(gòu)造器。Swift 的類并不繼承自一個通用基礎(chǔ)類。
有兩種方法來創(chuàng)建已聲明的類的實例:
調(diào)用類中聲明的構(gòu)造器,請參閱 構(gòu)造器。
如果沒有聲明構(gòu)造器,而且類的所有屬性都被賦予了初始值,調(diào)用類的默認(rèn)構(gòu)造器,請參閱 默認(rèn)構(gòu)造器。
類實例屬性可以用點語法(.
)來訪問,請參閱 訪問屬性。
類是引用類型。當(dāng)被賦予常量或變量,或者傳遞給函數(shù)作為參數(shù)時,類的實例會被引用,而不是被復(fù)制。關(guān)于引用類型的更多信息,請參閱 結(jié)構(gòu)體和枚舉是值類型。
可以使用擴展聲明來擴展類的行為,請參閱 擴展聲明。
類聲明語法
</a> 類聲明 → 特性列表可選 訪問級別修飾符可選 class 類名 泛型形參子句可選 類型繼承子句可選 類主體
類名 → 標(biāo)識符
類主體 → { 多條聲明可選 }
協(xié)議聲明 (protocol declaration) 可以為程序引入一個命名的協(xié)議類型。協(xié)議聲明只能在全局區(qū)域使用 protocol
關(guān)鍵字來進行聲明,并遵循如下形式:
protocol 協(xié)議名稱: 繼承的協(xié)議 {
協(xié)議成員聲明
}
協(xié)議的主體包含零個或多個協(xié)議成員聲明,這些成員描述了任何采納該協(xié)議的類型必須滿足的一致性要求。一個協(xié)議可以聲明采納者必須實現(xiàn)的某些屬性、方法、構(gòu)造器以及下標(biāo)。協(xié)議也可以聲明各種各樣的類型別名,叫做關(guān)聯(lián)類型,它可以指定協(xié)議的不同聲明之間的關(guān)系。協(xié)議聲明不能包括類、結(jié)構(gòu)體、枚舉或者其它協(xié)議的聲明。協(xié)議成員聲明會在后面進行討論。
協(xié)議類型可以繼承自任意數(shù)量的其它協(xié)議。當(dāng)一個協(xié)議類型繼承自其它協(xié)議的時候,來自其它協(xié)議的所有要求會聚合在一起,而且采納當(dāng)前協(xié)議的類型必須符合所有的這些要求。關(guān)于如何使用協(xié)議繼承的例子,請參閱 協(xié)議繼承。
注意
也可以使用協(xié)議合成類型來聚合多個協(xié)議的一致性要求,請參閱 協(xié)議合成類型 和 協(xié)議合成。
可以通過類型的擴展聲明來采納協(xié)議,從而為之前聲明的類型添加協(xié)議一致性。在擴展中,必須實現(xiàn)所有采納協(xié)議的要求。如果該類型已經(jīng)實現(xiàn)了所有的要求,可以讓這個擴展聲明的主體留空。
默認(rèn)地,符合某個協(xié)議的類型必須實現(xiàn)所有在協(xié)議中聲明的屬性、方法和下標(biāo)。即便如此,可以用 optional
聲明修飾符標(biāo)注協(xié)議成員聲明,以指定它們的實現(xiàn)是可選的。optional
修飾符僅僅可以用于使用 objc
特性標(biāo)記過的協(xié)議。因此,僅僅類類型可以采用并符合包含可選成員要求的協(xié)議。更多關(guān)于如何使用 optional
聲明修飾符的信息,以及如何訪問可選協(xié)議成員的指導(dǎo)——例如不能確定采納協(xié)議的類型是否實現(xiàn)了它們時——請參閱 可選協(xié)議要求
為了限制協(xié)議只能被類類型采納,需要使用 class
關(guān)鍵字來標(biāo)記協(xié)議,將 class
關(guān)鍵在寫在冒號后面的繼承的協(xié)議列表的首位。例如,下面的協(xié)議只能被類類型采納:
protocol SomeProtocol: class {
/* 這里是協(xié)議成員 */
}
任何繼承自標(biāo)記有 class
關(guān)鍵字的協(xié)議的協(xié)議也僅能被類類型采納。
注意
如果協(xié)議已經(jīng)用objc
特性標(biāo)記了,class
要求就隱式地應(yīng)用于該協(xié)議,無需顯式使用class
關(guān)鍵字。
協(xié)議類型是命名的類型,因此它們可以像其他命名類型一樣使用,正如 協(xié)議作為類型 所討論的。然而,不能構(gòu)造一個協(xié)議的實例,因為協(xié)議實際上不提供它們指定的要求的實現(xiàn)。
可以使用協(xié)議來聲明作為代理的類或者結(jié)構(gòu)體應(yīng)該實現(xiàn)的方法,正如 委托(代理)模式 中所述。
協(xié)議聲明語法
協(xié)議聲明 → 特性列表可選 訪問級別修飾符可選 protocol 協(xié)議名稱 類型繼承子句可選 協(xié)議主體
</a> 協(xié)議名稱 → 標(biāo)識符
協(xié)議主體 → { 協(xié)議成員聲明列表可選 }
協(xié)議成員聲明 → 協(xié)議屬性聲明
協(xié)議成員聲明 → 協(xié)議方法聲明
協(xié)議成員聲明 → 協(xié)議構(gòu)造器聲明
協(xié)議成員聲明 → 協(xié)議下標(biāo)聲明
協(xié)議成員聲明 → 協(xié)議關(guān)聯(lián)類型聲明
協(xié)議成員聲明列表 → 協(xié)議成員聲明 協(xié)議成員聲明列表可選
協(xié)議可以通過在協(xié)議聲明主體中引入一個協(xié)議屬性聲明,來聲明符合的類型必須實現(xiàn)的屬性。協(xié)議屬性聲明有一種特殊的變量聲明形式:
var 屬性名: 類型 { get set }
同其它協(xié)議成員聲明一樣,這些屬性聲明僅僅針對符合該協(xié)議的類型聲明了 getter 和 setter 要求,你不能在協(xié)議中直接實現(xiàn) getter 和 setter。
符合類型可以通過多種方式滿足 getter 和 setter 要求。如果屬性聲明包含 get
和 set
關(guān)鍵字,符合類型就可以用存儲型變量屬性或可讀可寫的計算型屬性來滿足此要求,但是屬性不能以常量屬性或只讀計算型屬性實現(xiàn)。如果屬性聲明僅僅包含 get
關(guān)鍵字的話,它可以作為任意類型的屬性被實現(xiàn)。關(guān)于如何實現(xiàn)協(xié)議中的屬性要求的例子,請參閱 屬性要求
另請參閱 變量聲明。
協(xié)議屬性聲明語法
協(xié)議屬性聲明 → 變量聲明頭 變量名稱 類型標(biāo)注 getter-setter關(guān)鍵字代碼塊
協(xié)議可以通過在協(xié)議聲明主體中引入一個協(xié)議方法聲明,來聲明符合的類型必須實現(xiàn)的方法。協(xié)議方法聲明和函數(shù)方法聲明有著相同的形式,但有兩項例外:它們不包括函數(shù)體,也不能包含默認(rèn)參數(shù)。關(guān)于如何實現(xiàn)協(xié)議中的方法要求的例子,請參閱 方法要求。
使用 static
聲明修飾符可以在協(xié)議聲明中聲明一個類型方法。結(jié)構(gòu)體實現(xiàn)這些方法時使用 static
聲明修飾符,類在實現(xiàn)這些方法時,除了使用 static
聲明修飾符,還可以選擇使用 class
聲明修飾符。通過擴展實現(xiàn)時亦是如此。
另請參閱 函數(shù)聲明。
協(xié)議方法聲明語法
協(xié)議方法聲明 → 函數(shù)頭 函數(shù)名 泛型形參子句可選 函數(shù)簽名
協(xié)議可以通過在協(xié)議聲明主體中引入一個協(xié)議構(gòu)造器聲明,來聲明符合的類型必須實現(xiàn)的構(gòu)造器。協(xié)議構(gòu)造器聲明 除了不包含實現(xiàn)主體外,和構(gòu)造器聲明有著相同的形式。
符合類型可以通過實現(xiàn)一個非可失敗構(gòu)造器或者 init!
可失敗構(gòu)造器來滿足一個非可失敗協(xié)議構(gòu)造器的要求,可以通過實現(xiàn)任意類型的構(gòu)造器來滿足一個可失敗協(xié)議構(gòu)造器的要求。
類在實現(xiàn)一個構(gòu)造器去滿足一個協(xié)議的構(gòu)造器要求時,如果這個類還沒有用 final
聲明修飾符標(biāo)記,這個構(gòu)造器必須用 required
聲明修飾符標(biāo)記。
另請參閱 構(gòu)造器聲明。
協(xié)議構(gòu)造器聲明語法
協(xié)議構(gòu)造器聲明 → 構(gòu)造器頭 泛型形參子句可選 參數(shù)子句 throws可選
協(xié)議構(gòu)造器聲明 → 構(gòu)造器頭 泛型形參子句可選 參數(shù)子句 rethrows
協(xié)議可以通過在協(xié)議聲明主體中引入一個協(xié)議下標(biāo)聲明,來聲明符合的類型必須實現(xiàn)的下標(biāo)。協(xié)議下標(biāo)聲明有一個特殊的下標(biāo)聲明形式:
subscript (參數(shù)列表) -> 返回類型 { get set }
下標(biāo)聲明只為符合類型聲明了 getter 和 setter 要求。如果下標(biāo)聲明包含 get
和 set
關(guān)鍵字,符合類型也必須實現(xiàn) getter 和 setter 子句。如果下標(biāo)聲明只包含 get
關(guān)鍵字,符合類型必須實現(xiàn) getter 子句,可以選擇是否實現(xiàn) setter 子句。
另請參閱 下標(biāo)聲明。
協(xié)議下標(biāo)聲明語法
協(xié)議下標(biāo)聲明 → 下標(biāo)頭 下標(biāo)結(jié)果 getter-setter關(guān)鍵字代碼塊
使用關(guān)鍵字 associatedtype
來聲明協(xié)議關(guān)聯(lián)類型。關(guān)聯(lián)類型為作為協(xié)議聲明的一部分,為某種類型提供了一個別名。關(guān)聯(lián)類型和泛型參數(shù)子句中的類型參數(shù)很相似,但是它們和 Self
一樣,用于協(xié)議中。Self
指代采納協(xié)議的類型。要獲得更多信息和例子,請參閱 關(guān)聯(lián)類型。
另請參閱 類型別名聲明。
協(xié)議關(guān)聯(lián)類型聲明語法
協(xié)議關(guān)聯(lián)類型聲明 → 類型別名頭 類型繼承子句可選 類型別名賦值可選
構(gòu)造器聲明會為程序中的類、結(jié)構(gòu)體或枚舉引入構(gòu)造器。構(gòu)造器使用關(guān)鍵字 init
來聲明,有兩種基本形式。
結(jié)構(gòu)體、枚舉、類可以有任意數(shù)量的構(gòu)造器,但是類的構(gòu)造器具有不同的規(guī)則和行為。不同于結(jié)構(gòu)體和枚舉,類有兩種構(gòu)造器,即指定構(gòu)造器和便利構(gòu)造器,請參閱 構(gòu)造過程。
采用如下形式聲明結(jié)構(gòu)體和枚舉的構(gòu)造器,以及類的指定構(gòu)造器:
init(參數(shù)列表) {
構(gòu)造語句
}
類的指定構(gòu)造器直接將類的所有屬性初始化。它不能調(diào)用類中的其他構(gòu)造器,如果類有超類,則必須調(diào)用超類的一個指定構(gòu)造器。如果該類從它的超類繼承了屬性,必須在調(diào)用超類的指定構(gòu)造器后才能修改這些屬性。
指定構(gòu)造器只能在類聲明中聲明,不能在擴展聲明中聲明。
結(jié)構(gòu)體和枚舉的構(gòu)造器可以調(diào)用其他已聲明的構(gòu)造器,從而委托其他構(gòu)造器來進行部分或者全部構(gòu)造過程。
要為類聲明一個便利構(gòu)造器,用 convenience
聲明修飾符來標(biāo)記構(gòu)造器聲明:
convenience init(參數(shù)列表) {
構(gòu)造語句
}
便利構(gòu)造器可以將構(gòu)造過程委托給另一個便利構(gòu)造器或一個指定構(gòu)造器。但是,類的構(gòu)造過程必須以一個將類中所有屬性完全初始化的指定構(gòu)造器的調(diào)用作為結(jié)束。便利構(gòu)造器不能調(diào)用超類的構(gòu)造器。
可以使用 required
聲明修飾符,將便利構(gòu)造器和指定構(gòu)造器標(biāo)記為每個子類都必須實現(xiàn)的構(gòu)造器。這種構(gòu)造器的子類實現(xiàn)也必須使用 required
聲明修飾符標(biāo)記。
默認(rèn)情況下,超類中的構(gòu)造器不會被子類繼承。但是,如果子類的所有存儲型屬性都有默認(rèn)值,而且子類自身沒有定義任何構(gòu)造器,它將繼承超類的構(gòu)造器。如果子類重寫了超類的所有指定構(gòu)造器,子類將繼承超類的所有便利構(gòu)造器。
和方法、屬性和下標(biāo)一樣,需要使用 override
聲明修飾符標(biāo)記重寫的指定構(gòu)造器。
注意
如果使用required
聲明修飾符標(biāo)記一個構(gòu)造器,在子類中重寫這種構(gòu)造器時,無需使用override
修飾符。
就像函數(shù)和方法,構(gòu)造器也可以拋出或者重拋錯誤,你可以在構(gòu)造器參數(shù)列表的圓括號之后使用 throws
或 rethrows
關(guān)鍵字來表明相應(yīng)的拋出行為。
關(guān)于在不同類型中聲明構(gòu)造器的例子,請參閱 構(gòu)造過程。
可失敗構(gòu)造器可以生成所屬類型的可選實例或者隱式解包可選實例,因此,這種構(gòu)造器通過返回 nil
來指明構(gòu)造過程失敗。
聲明生成可選實例的可失敗構(gòu)造器時,在構(gòu)造器聲明的 init
關(guān)鍵字后加追加一個問號(init?
)。聲明生成隱式解包可選實例的可失敗構(gòu)造器時,在構(gòu)造器聲明后追加一個嘆號(init!
)。使用 init?
可失敗構(gòu)造器生成結(jié)構(gòu)體的一個可選實例的例子如下。
struct SomeStruct {
let string: String
//生成一個 SomeStruct 的可選實例
init?(input: String) {
if input.isEmpty {
// 丟棄 self,并返回 nil
return nil
}
string = input
}
}
調(diào)用 init?
可失敗構(gòu)造器和調(diào)用非可失敗構(gòu)造器的方式相同,不過你需要處理可選類型的返回值。
if let actualInstance = SomeStruct(input: "Hello") {
// 利用 SomeStruct 實例做些事情
} else {
// SomeStruct 實例的構(gòu)造過程失敗,構(gòu)造器返回了 nil
}
可失敗構(gòu)造器可以在構(gòu)造器實現(xiàn)中的任意位置返回 nil
。
可失敗構(gòu)造器可以委托任意種類的構(gòu)造器。非可失敗可以委托其它非可失敗構(gòu)造器或者 init!
可失敗構(gòu)造器。非可失敗構(gòu)造器可以委托超類的 init?
可失敗指定構(gòu)造器,但是需要使用強制解包,例如 super.init()!
。
構(gòu)造過程失敗通過構(gòu)造器委托來傳遞。具體來說,如果可失敗構(gòu)造器委托的可失敗構(gòu)造器構(gòu)造過程失敗并返回 nil
,那么該可失敗構(gòu)造器也會構(gòu)造失敗并隱式地返回 nil
。如果非可失敗構(gòu)造器委托的 init!
可失敗構(gòu)造器構(gòu)造失敗并返回了 nil
,那么會發(fā)生運行時錯誤(如同使用 !
操作符去強制解包一個值為 nil
的可選值)。
子類可以用任意種類的指定構(gòu)造器重寫超類的可失敗指定構(gòu)造器,但是只能用非可失敗指定構(gòu)造器重寫超類的非可失敗指定構(gòu)造器。
更多關(guān)于可失敗構(gòu)造器的信息和例子,請參閱 可失敗構(gòu)造器。
構(gòu)造器聲明語法
</a> 構(gòu)造器聲明 → 構(gòu)造器頭 泛型形參子句可選 參數(shù)子句 throws可選 構(gòu)造器主體
構(gòu)造器聲明 → 構(gòu)造器頭 泛型形參子句可選 參數(shù)子句 rethrows可選 構(gòu)造器主體
構(gòu)造器頭 → 特性列表可選 聲明修飾符列表可選 init
構(gòu)造器頭 → 特性列表可選 聲明修飾符列表可選 init ?
構(gòu)造器頭 → 特性列表可選 聲明修飾符列表可選 init !
構(gòu)造器主體 → 代碼塊
析構(gòu)器聲明 (deinitializer declaration) 可以為類聲明一個析構(gòu)器。析構(gòu)器沒有參數(shù),遵循如下格式:
deinit {
語句
}
當(dāng)沒有任何強引用引用著類的對象,對象即將被釋放時,析構(gòu)器會被自動調(diào)用。析構(gòu)器只能在類主體的聲明中聲明,不能在類的擴展聲明中聲明,并且每個類最多只能有一個析構(gòu)器。
子類會繼承超類的析構(gòu)器,并會在子類對象將要被釋放時隱式調(diào)用。繼承鏈上的所有析構(gòu)器全部調(diào)用完畢后子類對象才會被釋放。
析構(gòu)器不能直接調(diào)用。
關(guān)于如何在類聲明中使用析構(gòu)器的例子,請參閱 析構(gòu)過程。
擴展聲明 (extension declaration) 可以擴展一個現(xiàn)存的類型的行為。擴展聲明使用關(guān)鍵字 extension
,遵循如下格式:
extension 類型名稱: 采納的協(xié)議 {
聲明語句
}
extension 類型名稱 where 要求 {
聲明語句
}
擴展聲明體可包含零個或多個聲明語句。這些聲明語句可以包括計算型屬性、計算型類型屬性、實例方法、類型方法、構(gòu)造器、下標(biāo)聲明,甚至是類、結(jié)構(gòu)體和枚舉聲明。擴展聲明不能包含析構(gòu)器、協(xié)議聲明、存儲型屬性、屬性觀察器或其他擴展聲明。關(guān)于擴展聲明的詳細(xì)討論,以及各種擴展聲明的例子,請參閱 擴展。
如果類型為類,結(jié)構(gòu)體,或枚舉類型,則擴展聲明會擴展相應(yīng)的類型。如果類型為協(xié)議類型,則擴展聲明會擴展所有遵守這個協(xié)議的類型。在擴展的協(xié)議體中聲明語句不能使用final
標(biāo)識符。
擴展聲明可以為現(xiàn)存的類、結(jié)構(gòu)體、枚舉添加協(xié)議一致性,但是不能為類添加超類,因此在擴展聲明的類型名稱的冒號后面僅能指定一個協(xié)議列表。
現(xiàn)存類型的屬性、方法、構(gòu)造器不能在擴展中被重寫。
擴展聲明可以包含構(gòu)造器聲明。這意味著,如果被擴展的類型在其他模塊中定義,構(gòu)造器聲明必須委托另一個在那個模塊中聲明的構(gòu)造器,以確保該類型能被正確地初始化。
擴展聲明語法
</a> 擴展聲明 → 特性可選 訪問級別修飾符可選 extension 類型標(biāo)識符 類型-繼承-子句可選 擴展主體
擴展聲明 → 特性可選 訪問級別修飾符可選 extension 類型標(biāo)識符 泛型-where-子句 擴展主體
擴展主體 → { 多條聲明可選 }
多條聲明 → 單條聲明 多條聲明 可選
單條聲明 → 聲明語句 | 編譯器-控制-語句
下標(biāo)聲明 (subscript declaration) 用于為特定類型的對象添加下標(biāo)支持,通常也用于為訪問集合、列表和序列中的元素提供語法便利。下標(biāo)聲明使用關(guān)鍵字 subscript
,形式如下:
subscript (參數(shù)列表) -> 返回類型 {
get {
語句
}
set(setter 名稱) {
語句
}
}
下標(biāo)聲明只能出現(xiàn)在類、結(jié)構(gòu)體、枚舉、擴展和協(xié)議的聲明中。
參數(shù)列表指定一個或多個用于在相關(guān)類型的下標(biāo)表達(dá)式中訪問元素的索引(例如,表達(dá)式 object[i]
中的 i
)。索引可以是任意類型,但是必須包含類型標(biāo)注。返回類型指定了被訪問的元素的類型。
和計算型屬性一樣,下標(biāo)聲明支持對元素的讀寫操作。getter 用于讀取值,setter 用于寫入值。setter 子句是可選的,當(dāng)僅需要一個 getter 子句時,可以將二者都忽略,直接返回請求的值即可。但是,如果提供了 setter 子句,就必須提供 getter 子句。
圓括號以及其中的 setter 名稱是可選的。如果提供了 setter 名稱,它會作為 setter 的參數(shù)名稱。如果不提供 setter 名稱,那么 setter 的參數(shù)名稱默認(rèn)是 value
。setter 名稱的類型必須與返回類型相同。
可以重載下標(biāo),只要參數(shù)列表或返回類型不同即可。還可以重寫繼承自超類的下標(biāo),此時必須使用 override
聲明修飾符聲明被重寫的下標(biāo)。
同樣可以在協(xié)議聲明中聲明下標(biāo),正如 協(xié)議下標(biāo)聲明 中所述。
更多關(guān)于下標(biāo)的信息和例子,請參閱 下標(biāo)。
下標(biāo)聲明語法
</a> 下標(biāo)聲明 → 下標(biāo)頭 下標(biāo)結(jié)果 代碼塊
下標(biāo)聲明 → 下標(biāo)頭 下標(biāo)結(jié)果 getter-setter代碼塊
下標(biāo)聲明 → 下標(biāo)頭 下標(biāo)結(jié)果 getter-setter關(guān)鍵字代碼塊
下標(biāo)頭 → 特性列表可選 聲明修飾符列表可選 subscript 參數(shù)子句
下標(biāo)結(jié)果 → -> 特性列表可選 類型
運算符聲明 (operator declaration) 會向程序中引入中綴、前綴或后綴運算符,使用關(guān)鍵字 operator
來聲明。
可以聲明三種不同的綴性:中綴、前綴和后綴。運算符的綴性指定了運算符與其運算對象的相對位置。
運算符聲明有三種基本形式,每種綴性各一種。運算符的綴性通過在 operator
關(guān)鍵字之前添加聲明修飾符 infix
,prefix
或 postfix
來指定。每種形式中,運算符的名字只能包含 運算符 中定義的運算符字符。
下面的形式聲明了一個新的中綴運算符:
infix operator 運算符名稱: 優(yōu)先級組
中綴運算符是二元運算符,置于兩個運算對象之間,例如加法運算符(+
)位于表達(dá)式 1 + 2
的中間。
中綴運算符可以選擇指定優(yōu)先級組。如果沒有為運算符設(shè)置優(yōu)先級組,Swift會設(shè)置默認(rèn)優(yōu)先級組DefaultPrecedence
,它的優(yōu)先級比三目優(yōu)先級TernaryPrecedence
要高,更多內(nèi)容參考優(yōu)先級組聲明
下面的形式聲明了一個新的前綴運算符:
prefix operator 運算符名稱 {}
出現(xiàn)在運算對象前邊的前綴運算符是一元運算符,例如表達(dá)式 !a
中的前綴非運算符(!
)。
前綴運算符的聲明中不指定優(yōu)先級,而且前綴運算符是非結(jié)合的。
下面的形式聲明了一個新的后綴運算符:
postfix operator 運算符名稱 {}
緊跟在運算對象后邊的后綴運算符是一元運算符,例如表達(dá)式 a!
中的后綴強制解包運算符(!
)。
和前綴運算符一樣,后綴運算符的聲明中不指定優(yōu)先級,而且后綴運算符是非結(jié)合的。
聲明了一個新的運算符以后,需要實現(xiàn)一個跟這個運算符同名的函數(shù)來實現(xiàn)這個運算符。如果是實現(xiàn)一個前綴或者后綴運算符,也必須使用相符的 prefix
或者 postfix
聲明修飾符標(biāo)記函數(shù)聲明。如果是實現(xiàn)中綴運算符,則不需要使用 infix
聲明修飾符標(biāo)記函數(shù)聲明。關(guān)于如何實現(xiàn)一個新的運算符的例子,請參閱 自定義運算符。
運算符聲明語法
前綴運算符聲明 → prefix 運算符 運算符 { }
</a> 后綴運算符聲明 → postfix 運算符 運算符 { }
中綴運算符聲明 → infix 運算符 運算符 { 中綴運算符屬性可選 }
中綴運算符組 → 優(yōu)先級組名稱
優(yōu)先級組聲明 (A precedence group declaration) 會向程序的中綴運算符引入一個全新的優(yōu)先級組。當(dāng)沒有用圓括號分組時,運算符優(yōu)先級反應(yīng)了運算符與它的操作數(shù)的關(guān)系的緊密程度。
優(yōu)先級組的聲明如下所示:
precedencegroup 優(yōu)先級組名稱{
higherThan: 較低優(yōu)先級組的名稱
lowerThan: 較高優(yōu)先級組的名稱
associativity: 結(jié)合性
assignment: 賦值性
}
較低優(yōu)先級組和較高優(yōu)先級組的名稱說明了新建的優(yōu)先級組是依賴于現(xiàn)存的優(yōu)先級組的。 lowerThan
優(yōu)先級組的屬性只可以引用當(dāng)前模塊外的優(yōu)先級組。當(dāng)兩個運算符為同一個操作數(shù)競爭時,比如表達(dá)式2 + 3 * 5
,優(yōu)先級更高的運算符將優(yōu)先參與運算。
注意
使用較低和較高優(yōu)先級組相互聯(lián)系的優(yōu)先級組必須保持單一層次關(guān)系,但它們不必是線性關(guān)系。這意味著優(yōu)先級組也許會有未定義的相關(guān)優(yōu)先級。這些優(yōu)先級組的運算符在沒有用圓括號分組的情況下是不能緊鄰著使用的。
Swift定義了大量的優(yōu)先級組來與標(biāo)準(zhǔn)庫的運算符配合使用,例如相加(+
)和相減(-
)屬于AdditionPrecedence
組,相乘(*
)和相除(/
)屬于MultiplicationPrecedence
組,詳細(xì)關(guān)于Swift標(biāo)準(zhǔn)庫中一系列運算符和優(yōu)先級組內(nèi)容,參閱Swift標(biāo)準(zhǔn)庫操作符參考。
運算符的結(jié)合性表示在沒有圓括號分組的情況下,同樣優(yōu)先級的一系列運算符是如何被分組的。你可以指定運算符的結(jié)合性通過上下文關(guān)鍵字left
、right
或者none
,如果沒有指定結(jié)合性,默認(rèn)是none
關(guān)鍵字。左關(guān)聯(lián)性的運算符是從左至右分組的,例如,相減操作符(-)是左關(guān)聯(lián)性的,所以表達(dá)式4 - 5 - 6
被分組為(4 - 5) - 6
,得出結(jié)果-7。右關(guān)聯(lián)性的運算符是從右往左分組的,指定為none
結(jié)合性的運算符就沒有結(jié)合性。同樣優(yōu)先級沒有結(jié)合性的運算符不能相鄰出現(xiàn),例如<
運算符是none
結(jié)合性,那表示1 < 2 < 3
就不是一個有效表達(dá)式。
優(yōu)先級組的賦值性表示在包含可選鏈操作時的運算符優(yōu)先級。當(dāng)設(shè)為true時,與優(yōu)先級組對應(yīng)的運算符在可選鏈操作中使用和標(biāo)準(zhǔn)庫中賦值運算符同樣的分組規(guī)則,當(dāng)設(shè)為false或者不設(shè)置,該優(yōu)先級組的運算符與不賦值的運算符遵循同樣的可選鏈規(guī)則。
優(yōu)先級組聲明語法
優(yōu)先級組聲明 → precedence優(yōu)先級組名稱{多優(yōu)先級組屬性可選 }
</a> 優(yōu)先級組屬性 → 優(yōu)先級組屬性多優(yōu)先級組屬性可選 { }
優(yōu)先級組屬性 → 優(yōu)先級組關(guān)系
優(yōu)先級組屬性 → 優(yōu)先級組賦值性
優(yōu)先級組屬性 → 優(yōu)先級組相關(guān)性
</a> 優(yōu)先級組關(guān)系 → higherThan:多優(yōu)先級組名稱
優(yōu)先級組關(guān)系 → lowerThan:多優(yōu)先級組名稱
優(yōu)先級組賦值 → assignment:布爾字面值
</a> 優(yōu)先級組結(jié)合性 → associativity:left
優(yōu)先級組結(jié)合性 → associativity:right
優(yōu)先級組結(jié)合性 → associativity:none
多優(yōu)先級組名稱 → 優(yōu)先級組名稱 | 優(yōu)先級組名稱 | 優(yōu)先級組名稱 優(yōu)先級組名稱 →標(biāo)識符
聲明修飾符都是關(guān)鍵字或上下文相關(guān)的關(guān)鍵字,可以修改一個聲明的行為或者含義??梢栽诼暶鞯奶匦裕ㄈ绻嬖冢┖鸵朐撀暶鞯年P(guān)鍵字之間,利用聲明修飾符的關(guān)鍵字或上下文相關(guān)的關(guān)鍵字指定一個聲明修飾符。
dynamic
該修飾符用于修飾任何兼容 Objective-C 的類的成員。訪問被 dynamic
修飾符標(biāo)記的類成員將總是由 Objective-C 運行時系統(tǒng)進行動態(tài)派發(fā),而不會由編譯器進行內(nèi)聯(lián)或消虛擬化。
因為被標(biāo)記 dynamic
修飾符的類成員會由 Objective-C 運行時系統(tǒng)進行動態(tài)派發(fā),所以它們會被隱式標(biāo)記 objc
特性。
final
該修飾符用于修飾類或類中的屬性、方法以及下標(biāo)。如果用它修飾一個類,那么這個類不能被繼承。如果用它修飾類中的屬性、方法或下標(biāo),那么它們不能在子類中被重寫。
lazy
該修飾符用于修飾類或結(jié)構(gòu)體中的存儲型變量屬性,表示該屬性的初始值最多只被計算和存儲一次,且發(fā)生在它被第一次訪問時。關(guān)于如何使用 lazy
修飾符的例子,請參閱 惰性存儲型屬性。
optional
該修飾符用于修飾協(xié)議中的屬性、方法以及下標(biāo)成員,表示符合類型可以不實現(xiàn)這些成員要求。
只能將 optional
修飾符用于被 objc
特性標(biāo)記的協(xié)議。這樣一來,就只有類類型可以采納并符合擁有可選成員要求的協(xié)議。關(guān)于如何使用 optional
修飾符,以及如何訪問可選協(xié)議成員(比如,不確定符合類型是否已經(jīng)實現(xiàn)了這些可選成員)的信息,請參閱 可選協(xié)議要求。
required
該修飾符用于修飾類的指定構(gòu)造器或便利構(gòu)造器,表示該類所有的子類都必須實現(xiàn)該構(gòu)造器。在子類實現(xiàn)該構(gòu)造器時,必須同樣使用 required
修飾符修飾該構(gòu)造器。
weak
該修飾符用于修飾變量或存儲型變量屬性,表示該變量或?qū)傩猿钟衅浯鎯Φ膶ο蟮娜跻?。這種變量或?qū)傩缘念愋捅仨毷强蛇x的類類型。使用 weak
修飾符可避免強引用循環(huán)。關(guān)于 weak
修飾符的更多信息和例子,請參閱 弱引用。
Swift 提供了三個級別的訪問控制:public
、internal
和 private
??梢允褂靡韵氯我庖环N訪問級別修飾符來指定聲明的訪問級別。訪問控制在 訪問控制 中有詳細(xì)討論。
public
該修飾符表示聲明可被同模塊的代碼訪問,只要其他模塊導(dǎo)入了聲明所在的模塊,也可以進行訪問。
internal
該修飾符表示聲明只能被同模塊的代碼訪問。默認(rèn)情況下,絕大多數(shù)聲明會被隱式標(biāo)記 internal
訪問級別修飾符。
private
該修飾符表示聲明只能被所在源文件的代碼訪問。
以上訪問級別修飾符都可以選擇帶上一個參數(shù),該參數(shù)由一對圓括號和其中的 set
關(guān)鍵字組成(例如,private(set)
)。使用這種形式的訪問級別修飾符來限制某個屬性或下標(biāo)的 setter 的訪問級別低于其本身的訪問級別,正如 Getter 和 Setter 中所討論的。
聲明修飾符的語法
聲明修飾符 → class | convenience| dynamic | final | infix | lazy | mutating | nonmutating | optional | override | postfix | prefix | required | static | unowned | unowned ( safe ) | unowned ( unsafe ) | weak
聲明修飾符 → 訪問級別修飾符
聲明修飾符列表 → 聲明修飾符 聲明修飾符列表可選
訪問級別修飾符 → internal | internal ( set )
訪問級別修飾符 → private | private ( set )
訪問級別修飾符 → public | public ( set )