This commit is contained in:
geek5nan
2014-06-10 11:50:20 +08:00
49 changed files with 1757 additions and 127 deletions

View File

@ -24,7 +24,7 @@
* 基本操作符(完成 By @xielingwang)
* 字符串和字符(完成 By @wh1100717)
* 集合类型(认领)
* 控制流(@vclwei 认领)
* 控制流(@vclwei, @coverxit, @NicePiao 认领)
* 函数(完成 By @honghaoz)
* 闭包(完成 By @wh1100717)
* 枚举(完成 By @yankuangshi)
@ -40,19 +40,19 @@
* 类型检查(完成 By @xiehurricane)
* 嵌套类型(完成 By @Lin-H)
* 扩展(完成 By @lyuka)
* 协议(@geek5nan 认领)
* 协议(完成 By @geek5nan)
* 泛型(完成 By @takalard)
* 高级操作符(@xielingwang 认领)
* 语言参考
* 关于语言参考(完成 By @ChildhoodAndy)
* 词法结构(@superkam 认领)
* 类型(@lyuka 认领)
* 词法结构(完成 By @superkam)
* 类型(完成 By @lyuka)
* 表达式(@sg552 认领)
* 语句(完成 By @coverxit)
* 声明(@marsprince 认领)
* 特性(完成 By @Hawstein)
* 模式(@honghaoz 认领)
* 泛型参数(@fd5788 认领)
* 泛型参数(完成 By @fd5788)
* 语法总结(@StanZhai 认领)
# 更新频率

View File

@ -46,7 +46,7 @@
<div class="book" data-level="1.1" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="1.1" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_4">
<section class="normal" id="section-gitbook_9">
<h1 id="-swift">关于 Swift</h1>
<p>Swift 是一种新的编程语言,用于编写 iOS 和 OS X 应用。Swift 结合了 C 和 Objective-C 的优点并且不受C的兼容性的限制。Swift 使用安全的编程模式并添加了很多新特性这将使编程更简单扩展性更强也更有趣。除此之外Swift 还支持人见人爱的 Cocoa 和 Cocoa Touch 框架。拥有了这些特性Swift将重新定义软件开发。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="1.2" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="1.2" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_5">
<section class="normal" id="section-gitbook_10">
<h1 id="swift-">Swift 初见</h1>
<p>本页内容包括:</p>
@ -794,7 +794,7 @@ func lessThanTen(number: Int) -&gt; Bool {
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)
</code></pre><p>函数实际上是一种特殊的闭包,你可以使用<code>{}</code>来创建一个匿名闭包。使用<code>in</code>来分割参数返回类型</p>
</code></pre><p>函数实际上是一种特殊的闭包,你可以使用<code>{}</code>来创建一个匿名闭包。使用<code>in</code>来分割参数返回值与执行体</p>
<pre><code>numbers.map({
(number: Int) -&gt; Int in
let result = 3 * number

View File

@ -46,7 +46,7 @@
<div class="book" data-level="1" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="1" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_6">
<section class="normal" id="section-gitbook_11">
<h1 id="-swift">欢迎使用 Swift</h1>
<p>在本章中您将了解 Swift 的特性和开发历史,并对 Swift 有一个初步的了解。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.1" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.1" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_8">
<section class="normal" id="section-gitbook_13">
<h1 id="-">基础部分</h1>
<p>Swift 是 iOS 和 OS X 应用开发的一门新语言。然而,如果你有 C 或者 Objective-C 开发经验的话,你会发现 Swift 的很多内容都是你熟悉的。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.2" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.2" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_30">
<section class="normal" id="section-gitbook_35">
<h1 id="-">基础运算符</h1>
<p>运算符是检查, 改变, 合并值的特殊符号或短语. 例如, 加号 <code>+</code> 把计算两个数的和(如 <code>let i = 1 + 2</code>). 复杂些的运行算包括逻辑与<code>&amp;&amp;</code>(如 <code>if enteredDoorCode &amp;&amp; passedRetinaScan</code>), 还有自增运算符 <code>++i</code> 这样让自身加一的便捷运算.</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.3" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.3" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_9">
<section class="normal" id="section-gitbook_14">
<h1 id="-strings-and-characters-">字符串和字符 (Strings and Characters)</h1>
<p>本页包含内容:</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.4" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.4" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_21">
<section class="normal" id="section-gitbook_26">
<h1 id="-collection-types-">集合类型 (Collection Types)</h1>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.5" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.5" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_22">
<section class="normal" id="section-gitbook_27">
<h1 id="-">控制流</h1>
<p>Swift提供了类似C语言的流程控制结构包括将任务执行多次的<code>for</code><code>while</code>循环,基于特定条件选择执行不同分支的<code>if</code><code>switch</code>语句,还有控制流程跳转到其他代码的<code>break</code><code>continue</code>语句。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.6" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.6" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_23">
<section class="normal" id="section-gitbook_28">
<h1 id="-functions-">函数Functions</h1>
<p>本页包含内容:</p>
@ -770,9 +770,8 @@
return s1 + joiner + s2
}
</code></pre><p>在这个例子中Swift自动为<code>joiner</code>提供了外部参数名。因此,当函数调用时,外部参数名必须使用,这样使得参数的用途变得清晰。</p>
<pre><code> func join(s1: String, s2: String, joiner: String = &quot; &quot;) -&gt; String {
return s1 + joiner + s2
}
<pre><code> join(&quot;hello&quot;, &quot;world&quot;, joiner: &quot;-&quot;)
// returns &quot;hello-world&quot;
</code></pre><blockquote>
<p>注意:
你可以使用<code>下划线_</code>作为默认值参数的外部参数名,这样可以在调用时不用提供外部参数名。但是给带默认值的参数命名总是更加合适的。</p>
@ -821,7 +820,7 @@
</blockquote>
<h3 id="-in-out-parameters-">输入输出参数In-Out Parameters</h3>
<p>变量参数正如上面所述仅仅能在函数体内被更改。如果你想要一个函数可以修改参数的值并且想要在这些修改在函数调用结束后仍然存在那么就应该把这个参数定义为输入输出参数In-Out Parameters</p>
<p>定义一个输入输出参数时,在参数定前加<code>inout</code>关键字。一个输入输出参数有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值。</p>
<p>定义一个输入输出参数时,在参数定前加<code>inout</code>关键字。一个输入输出参数有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值。</p>
<p>你只能传入一个变量作为输入输出参数。你不能传入常量或者字面量literal value因为这些量是不能被修改的。当传入的参数作为输入输出参数时需要在参数前加<code>&amp;</code>符,表示这个值可以被函数修改。</p>
<blockquote>
<p>注意:

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.7" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.7" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_24">
<section class="normal" id="section-gitbook_29">
<h1 id="-">闭包</h1>
<p>本页内容包含:</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.8" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.8" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,20 +587,20 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_25">
<section class="normal" id="section-gitbook_30">
<h1 id="-">枚举</h1>
<p>本页内容包含:</p>
<ul>
<li>枚举语法</li>
<li>匹配枚举值与<code>Swith</code>语句</li>
<li>实例associated values</li>
<li>关联associated values</li>
<li>原始值raw values</li>
</ul>
<p>枚举enumeration定义了一个通用类型的一组相关的值使你可以在你的代码中以一个安全的方式来使用这些值。</p>
<p>如果你熟悉C语言你就会知道在C语言中枚举指定相关名称为一组整型值。Swift中的枚举更加灵活不必给每一个枚举成员enumeration member提供一个值。如果一个值被认为是“原始”值被提供给每个枚举成员则该值可以是一个字符串一个字符或是一个整型值或浮点值。</p>
<p>此外,枚举成员可以指定任何类型的实例值存储到枚举成员值中就像其他语言中的联合体unions和变体variants。你可以定义一组通用的相关成员作为枚举的一部分每一组都有不同的一组与它相关的适当类型的数值。</p>
<p>在Swift中枚举类型是一等first-class类型。它们采用了很多传统上只被类class)所支持的特征例如计算型属性computed properties),用于提供关于枚举当前值的附加信息, 实例方法instance methods用于提供和枚举所代表的值相关联的功能。枚举也可以定义构造函数initializers来提供一个初始成员值可以在原始的实现基础上扩展它们的功能可以遵守协议protocols来提供标准的功能。</p>
<p>此外,枚举成员可以指定任何类型的关联值存储到枚举成员值中就像其他语言中的联合体unions和变体variants。你可以定义一组通用的相关成员作为枚举的一部分每一组都有不同的一组与它相关的适当类型的数值。</p>
<p>在Swift中枚举类型是一等first-class类型。它们采用了很多传统上只被类class)所支持的特征例如计算型属性computed properties)用于提供关于枚举当前值的附加信息实例方法instance methods用于提供和枚举所代表的值相关联的功能。枚举也可以定义构造函数initializers来提供一个初始成员值可以在原始的实现基础上扩展它们的功能可以遵守协议protocols来提供标准的功能。</p>
<p>欲了解更多相关功能请参见属性Properties方法Methods构造过程Initialization扩展Extensions和协议Protocols</p>
<h2 id="-">枚举语法</h2>
<p>使用<code>enum</code>关键词并且把它们的整个定义放在一对大括号内:</p>
@ -655,9 +655,9 @@ default:
println(&quot;Not a safe place for humans&quot;)
}
// prints &quot;Mostly harmless”
</code></pre><h2 id="-associated-values-">实例Associated Values</h2>
<p>上一小节的例子演示了一个枚举的成员是如何被定义(分类)的。你可以为<code>Planet.Earth</code>设置一个常量或则变量,并且在之后查看这个值。然而,有时候会很有用如果能够把其他类型的实例值和成员值一起存储起来。这能让你随着成员值存储额外的自定义信息,并且当每次你在代码中利用该成员时允许这个信息产生变化。</p>
<p>你可以定义Swift的枚举存储任何类型的实例如果需要的话每个成员的数据类型可以是各不相同的。枚举的这种特性跟其他语言中的可辨识联合discriminated unions标签联合tagged unions或者变体variants相似。</p>
</code></pre><h2 id="-associated-values-">关联Associated Values</h2>
<p>上一小节的例子演示了一个枚举的成员是如何被定义(分类)的。你可以为<code>Planet.Earth</code>设置一个常量或则变量,并且在之后查看这个值。然而,有时候会很有用如果能够把其他类型的关联值和成员值一起存储起来。这能让你随着成员值存储额外的自定义信息,并且当每次你在代码中利用该成员时允许这个信息产生变化。</p>
<p>你可以定义Swift的枚举存储任何类型的关联如果需要的话每个成员的数据类型可以是各不相同的。枚举的这种特性跟其他语言中的可辨识联合discriminated unions标签联合tagged unions或者变体variants相似。</p>
<p>例如假设一个库存跟踪系统需要利用两种不同类型的条形码来跟踪商品。有些商品上标有UPC-A格式的一维码它使用数字0到9.每一个条形码都有一个代表“数字系统”的数字该数字后接10个代表“标识符”的数字。最后一个数字是“检查”位用来验证代码是否被正确扫描</p>
<p><img width="252" height="120" a"" src="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/barcode_UPC_2x.png"></p>
<p>其他商品上标有QR码格式的二维码它可以使用任何ISO8859-1字符并且可以编码一个最多拥有2,953字符的字符串:</p>
@ -669,15 +669,15 @@ default:
case QRCode(String)
}
</code></pre><p>以上代码可以这么理解:</p>
<p>“定义一个名为<code>Barcode</code>的枚举类型,它可以是<code>UPCA</code>的一个实例值(<code>Int</code><code>Int</code><code>Int</code>),或者<code>QRCode</code>的一个字符串类型(<code>String</code>实例值。”</p>
<p>这个定义不提供任何<code>Int</code><code>String</code>的实际值,它只是定义了,当<code>Barcode</code>常量和变量等于<code>Barcode.UPCA</code><code>Barcode.QRCode</code>时,实例值的类型。</p>
<p>“定义一个名为<code>Barcode</code>的枚举类型,它可以是<code>UPCA</code>的一个关联值(<code>Int</code><code>Int</code><code>Int</code>),或者<code>QRCode</code>的一个字符串类型(<code>String</code>关联值。”</p>
<p>这个定义不提供任何<code>Int</code><code>String</code>的实际值,它只是定义了,当<code>Barcode</code>常量和变量等于<code>Barcode.UPCA</code><code>Barcode.QRCode</code>时,关联值的类型。</p>
<p>然后可以使用任何一种条码类型创建新的条码,如:</p>
<pre><code>var productBarcode = Barcode.UPCA(8, 85909_51226, 3)
</code></pre><p>以上例子创建了一个名为<code>productBarcode</code>的新变量,并且赋给它一个<code>Barcode.UPCA</code>实例元组值<code>(8, 8590951226, 3)</code>。提供的“标识符”值在整数字中有一个下划线,使其便于阅读条形码。</p>
</code></pre><p>以上例子创建了一个名为<code>productBarcode</code>的新变量,并且赋给它一个<code>Barcode.UPCA</code>关联元组值<code>(8, 8590951226, 3)</code>。提供的“标识符”值在整数字中有一个下划线,使其便于阅读条形码。</p>
<p>同一个商品可以被分配给一个不同类型的条形码,如:</p>
<pre><code>productBarcode = .QRCode(&quot;ABCDEFGHIJKLMNOP&quot;)
</code></pre><p>这时,原始的<code>Barcode.UPCA</code>和其整数值被新的<code>Barcode.QRCode</code>和其字符串值所替代。条形码的常量和变量可以存储一个<code>.UPCA</code>或者一个<code>.QRCode</code>(连同它的实例值),但是在任何指定时间只能存储其中之一。</p>
<p>像以前那样不同的条形码类型可以使用一个switch语句来检查然而这次实例值可以被提取作为switch语句的一部分。你可以在<code>switch</code>的case分支代码中提取每个实例值作为一个常量(用<code>let</code>前缀)或者作为一个变量(用<code>var</code>前缀)来使用:</p>
</code></pre><p>这时,原始的<code>Barcode.UPCA</code>和其整数值被新的<code>Barcode.QRCode</code>和其字符串值所替代。条形码的常量和变量可以存储一个<code>.UPCA</code>或者一个<code>.QRCode</code>(连同它的关联值),但是在任何指定时间只能存储其中之一。</p>
<p>像以前那样不同的条形码类型可以使用一个switch语句来检查然而这次关联值可以被提取作为switch语句的一部分。你可以在<code>switch</code>的case分支代码中提取每个关联值作为一个常量(用<code>let</code>前缀)或者作为一个变量(用<code>var</code>前缀)来使用:</p>
<pre><code>switch productBarcode {
case .UPCA(let numberSystem, let identifier, let check):
println(&quot;UPC-A with value of \(numberSystem), \(identifier), \(check).&quot;)
@ -685,7 +685,7 @@ case .QRCode(let productCode):
println(&quot;QR code with value of \(productCode).&quot;)
}
// prints &quot;QR code with value of ABCDEFGHIJKLMNOP.”
</code></pre><p>如果一个枚举成员的所有实例值被提取为常量,或者它们全部被提取为变量,为了简洁,你可以只放置一个<code>var</code>或者<code>let</code>标注在成员名称前:</p>
</code></pre><p>如果一个枚举成员的所有关联值被提取为常量,或者它们全部被提取为变量,为了简洁,你可以只放置一个<code>var</code>或者<code>let</code>标注在成员名称前:</p>
<pre><code>switch productBarcode {
case let .UPCA(numberSystem, identifier, check):
println(&quot;UPC-A with value of \(numberSystem), \(identifier), \(check).&quot;)
@ -694,7 +694,7 @@ case let .QRCode(productCode):
}
// prints &quot;QR code with value of ABCDEFGHIJKLMNOP.&quot;
</code></pre><h2 id="-raw-values-">原始值Raw Values</h2>
<p>实例值小节的条形码例子中演示了一个枚举的成员如何声明它们存储不同类型的实例值。作为实例值的替代,枚举成员可以被默认值(称为原始值)预先填充,其中这些原始值具有相同的类型。</p>
<p>关联值小节的条形码例子中演示了一个枚举的成员如何声明它们存储不同类型的关联值。作为关联值的替代,枚举成员可以被默认值(称为原始值)预先填充,其中这些原始值具有相同的类型。</p>
<p>这里是一个枚举成员存储原始ASCII值的例子</p>
<pre><code>enum ASCIIControlCharacter: Character {
case Tab = &quot;\t&quot;
@ -702,7 +702,7 @@ case let .QRCode(productCode):
case CarriageReturn = &quot;\r&quot;
}
</code></pre><p>在这里,称为<code>ASCIIControlCharacter</code>的枚举的原始值类型被定义为字符型<code>Character</code>并被设置了一些比较常见的ASCII控制字符。字符值的描述请详见字符串和字符<code>Strings and Characters</code>部分。</p>
<p>注意,原始值和实例值是不相同的。当你开始在你的代码中定义枚举的时候原始值是被预先填充的值像上述三个ASCII码。对于一个特定的枚举成员它的原始值始终是相同的。实例值是当你在创建一个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做得时候,它的值可以是不同的。</p>
<p>注意,原始值和关联值是不相同的。当你开始在你的代码中定义枚举的时候原始值是被预先填充的值像上述三个ASCII码。对于一个特定的枚举成员它的原始值始终是相同的。关联值是当你在创建一个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做得时候,它的值可以是不同的。</p>
<p>原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。当整型值被用于原始值,如果其他枚举成员没有值时,它们会自动递增。</p>
<p>下面的枚举是对之前<code>Planet</code>这个枚举的一个细化利用原始整型值来表示每个planet在太阳系中的顺序</p>
<pre><code>enum Planet: Int {

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.9" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.9" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_26">
<section class="normal" id="section-gitbook_31">
<h3 id="-">类和结构体</h3>
<p>本页包含内容:</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.10" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.10" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_27">
<section class="normal" id="section-gitbook_32">
<h1 id="-properties-">属性 (Properties)</h1>
<p><strong>属性</strong>将值跟特定的类、结构或枚举关联。一种是存储属性,把常量或变量的值作为实例的一部分,一种是计算属性,它计算一个值。计算属性可以用于类、结构和枚举里,存储属性只能用于类和结构。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.11" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.11" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_28">
<section class="normal" id="section-gitbook_33">
<h1 id="-methods-">方法(Methods)</h1>
<p><strong>方法</strong>是与某些特定类型相关联的功能/函数。类、结构体、枚举都可以定义实例方法;实例方法为指定类型的实例封装了特定的任务与功能。类、结构体、枚举也可以定义类(型)方法(type itself)类型方法与类型自身相关联。类型方法与Objective-C中的类方法(class methods)相似。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.12" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.12" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_29">
<section class="normal" id="section-gitbook_34">
<h1 id="-subscripts-">下标 (Subscripts)</h1>
<p>下标可以定义在类(Class)、结构体(structures)和枚举(enumerations)这些目标中,可以认为是访问对象、集合或序列的快捷方式。举例来说,用下标访问一个数组(Array)实例中的元素可以这样写 <code>someArray[index]</code> ,访问字典(Dictionary)实例中的元素可以这样写 <code>someDictionary[key]</code>,而不需要再调用实例的某个方法来获得元素的值。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.13" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.13" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_7">
<section class="normal" id="section-gitbook_12">
<h1 id="-">继承</h1>
<p>一个类可以继承另一个类的方法属性和其它特性。当一个类继承其它类继承类叫子类被继承类叫超类或父类。在Swift中继承是区分「类」与其它类型的一个基本特征。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.14" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.14" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.15" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.15" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_32">
<section class="normal" id="section-gitbook_37">
<h1 id="-">析构过程</h1>
<p>在一个类的实例被释放之前析构函数被立即调用。用关键字deinit来标示析构函数类似于初始化函数用init来标示。析构函数只适用于类类型。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.16" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.16" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_33">
<section class="normal" id="section-gitbook_38">
<h1 id="-">自动引用计数</h1>
<p>本页包含内容:</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.17" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.17" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_34">
<section class="normal" id="section-gitbook_39">
<h1 id="optional-chaining">Optional Chaining</h1>
<p>可选链Optional Chaining是一种可以请求和调用属性、方法及子脚本的过程它的自判断性体现于请求或调用的目标当前可能为空<code>nil</code>)。如果自判断的目标有值,那么调用就会成功;相反,如果选择的目标为空(<code>nil</code>),则这种调用将返回空(<code>nil</code>)。多次请求或调用可以被链接在一起形成一个链,如果任何一个节点为空(<code>nil</code>)将导致整个链失效。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.18" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.18" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_35">
<section class="normal" id="section-gitbook_40">
<h1 id="-type-casting-">类型检查Type Casting</h1>
<p>ps为了方便各位检验所以保留了英文可删。

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.19" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.19" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_36">
<section class="normal" id="section-gitbook_41">
<h1 id="-">类型嵌套</h1>
<p>本页包含内容:</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.20" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.20" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_37">
<section class="normal" id="section-gitbook_42">
<h1 id="-extensions-">扩展Extensions</h1>
<hr>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.21" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.21" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,6 +587,487 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_44">
<h1 id="-">协议</h1>
<p><code>Protocol(协议)</code>定义了用于完成某项任务或功能的方法,属性等,它不具备任何功能的细节实现,只用来<strong>统一</strong>方法,属性等的名称和其类型.(<em>译者注: 其他语言中也把 <code>Portocol</code> 称为 <code>Interface(接口)</code></em> ).协议可以被<code>类,枚举,结构体</code>采纳并实现,任意满足了协议要求的<code>类,枚举,结构体</code>被称之为<code>协议遵循者</code>.</p>
<p>协议可以要求其<code>遵循者</code>必须具备的某些特定的<code>属性,方法,操作符,下标</code>.</p>
<h2 id="-">协议的语法</h2>
<p><code>协议</code>的定义和<code>类,结构体,枚举</code>的定义非常相似:</p>
<pre><code>protocol SomeProtocol {
// 此处书写协议的内容
}
</code></pre><p><code>类型名称</code>后加上<code>协议名称</code> ,并用冒号<code>:</code>分隔,从而实现协议;当实现多个协议时,各协议之间用逗号<code>,</code>分隔.</p>
<pre><code>struct SomeStructure: FirstProtocol, AnotherProtocol{
// 此处书写结构体的定义
}
</code></pre><p>当某个类实现了协议,并含有父类时,应当把父类名放在所有的协议名称之前</p>
<pre><code>class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol{
// 此处书写类的定义
}
</code></pre><h2 id="-">属性要求</h2>
<p><code>协议</code>能够要求其<code>遵循者</code>必须拥有<strong>特定名称和类型</strong><code>实例属性(instance property)</code><code>类属性 (type property)</code>,也可以指定协议中的属性的<code>settable</code><code>gettable</code>,但它并不要求<code>属性</code><code>存储型属性(stored property)</code>还是<code>计算型属性(calculate property)</code>.</p>
<p>当协议要求其中的<code>某个属性</code><code>gettable</code>时,即使实现了它的<code>setter</code>也不会出错. (<em>译者注:此小节术语较多,可参阅属性章节</em>).</p>
<p>属性通常被声明为变量,通过前置<code>var</code>关键字. 在属性声明后写上<code>{ get set }</code>指定属性为可读写的.<code>{ get }</code>用来描述属性为可读的.</p>
<pre><code>protocol SomeProtocol {
var musBeSettable : Int { get set }
var doesNotNeedToBeSettable: Int { get }
}
</code></pre><p>当协议用来被类实现时,使用<code>class</code>关键字来说明该属性为类成员 ; 当协议被结构体或枚举实现时,则使用<code>static</code>关键字来说明</p>
<pre><code>protocol AnotherProtocol {
class var someTypeProperty: Int { get set }
}
</code></pre><p>下边的协议包含了一个实例属性.</p>
<pre><code>protocol FullyNamed {
var fullName: string { get }
}
</code></pre><p><code>FullyNamed</code> 定义了一个拥有 <code>fullName</code> 属性的协议. 该协议要求其 <code>遵循者</code> 必须拥有一个名为 <code>fullName</code>, 类型为 <code>String</code> 的可读属性.</p>
<p>下例是一个<code>遵循</code><code>FullyNamed</code> 协议的简单结构体</p>
<pre><code>struct Person: FullyNamed{
var fullName: String
}
let john = Person(fullName: &quot;John Appleseed&quot;)
//john.fullName 为 &quot;John Appleseed&quot;
</code></pre><p>定义一个名为<code>Person</code>并实现了<code>FullyNamed</code>协议的结构体. 每一个<code>Person</code>实例都拥有一个<code>String</code>类型,名为<code>fullName</code><code>存储型属性</code>,它满足了<code>FullyNamed</code>协议的要求,也就是说 <code>Person</code>完整的遵循了该协议.(如果协议未被完整遵循,Swift编译时会报出错误). </p>
<p>下例是一个遵循了<code>FullyNamed</code>协议的类:</p>
<pre><code>class Starship: FullyNamed {
var prefix: String?
var name: String
init(name: String, prefix: Stirng? = nil ) {
self.anme = name
self.prefix = prefix
}
var fullName: String {
return (prefix ? prefix ! + &quot; &quot; : &quot; &quot;) + name
}
}
var ncc1701 = Starship(name: &quot;Enterprise&quot;, prefix: &quot;USS&quot;)
// ncc1701.fullName == &quot;USS Enterprise&quot;
</code></pre><p>该类将<code>fullName</code>实现为<code>计算型只读属性</code>.它的每一个实例都有一个名为<code>name</code>的必备属性和一个名为<code>prefix</code>的可选属性. 当<code>prefix</code>存在时,将<code>prefix</code>插入到<code>name</code>之前来为<code>Starship</code>构建<code>fullName</code></p>
<h2 id="-">方法要求</h2>
<p><code>协议</code>可以要求其<code>遵循者</code>必备某些特定的<code>实例方法</code><code>类方法</code>. 这些方法作为<code>协议</code>的一部分,像普通的方法一样写在协议体中,但却不需要方法体.而且,协议中的方法同样支持可变参数. </p>
<blockquote>
<p>笔记: 协议中的<code>方法</code>的语法同普通<code>方法</code>一样,但是不支持<code>默认参数</code>. </p>
</blockquote>
<p>在协议中定义<code>类方法</code><code>类属性</code>一样,只需在方法前加上<code>class</code>关键字; 当协议用于被<code>枚举</code><code>结构体</code>遵循时,<code>类方法</code>的关键字需要换为<code>static</code>:</p>
<pre><code>protocol SomeProtocol {
class func someTypeMethod()
}
</code></pre><p>下边是拥有一个实例方法的协议的例子</p>
<pre><code>protocol RandomNumberGenerator {
func random() -&gt; Double
}
</code></pre><p><code>RandomNumberGenerator</code> 协议要求其<code>遵循者</code>必须拥有一个名为<code>random</code>, 返回值类型为<code>Double</code> 的实例方法. (这里假设随机数在 [0,1] 之间). 该协议只为生成随机数提供了一个统一的函数名称,而不去做具体的实现工作. </p>
<p>这里有一个名为<code>LinearCongruentialGenerator</code><code>遵循</code><code>RandomNumberGenerator</code>协议的类. 该类实现了名为 <em>linear congruential generator</em>(线性同余生成器) 的假随机数算法</p>
<pre><code>class LinearCongruentialGenerator: RandomNumberGenerator {
var lastRandom = 42.0
let m = 139968.0
let a = 3877.0
let c = 29573.0
func random() -&gt; Double {
lastRandom = ((lastRandom * a + c) % m)
return lastRandom / m
}
}
let generator = LinearCongruentialGenerator()
println(&quot;Here&#39;s a random number: \(generator.random())&quot;)
// 输出 : &quot;Here&#39;s a random number: 0.37464991998171&quot;
println(&quot;And another one: \(generator.random())&quot;)
// 输出 : &quot;And another one: 0.729023776863283&quot;
</code></pre><h2 id="-">突变方法要求</h2>
<p>有时不得不在方法中改变实例的所属的类型.在基于<code>Value Type</code>的实例方法(<em>译者注:指结构体和枚举中的方法</em>)的<code>func</code>前加上<code>mutating</code>关键字来表明该方法允许改变该实例和其属性的所属类型. 这一突变过程在 [Modifyting Value Types from Within Instance Methods][1] 一节中有详细描述.</p>
<p>如果你打算在协议中定义一个能够改变实例所属类型的实例方法,只需要在方法前加上<code>mutating</code>关键字.使得结构体和枚举遵循该协议.(<em>译者注:类中的变量为 Reference Type ,可以轻易的改变实例及其属性的类型 . 而结构体和枚举中的变量都为 Value Type, 因此需要加上<code>mutating</code>关键字才能更改它们的所属类型</em>)</p>
<blockquote>
<p>当协议的实例方法标记为<code>mutating</code>时,在结构体或枚举的实现该方法时中,<code>mutating</code>关键字是不必可少的;当使用类遵循该协议时,则不需要为这个实例方法前加 <code>mutating</code> 关键字.</p>
</blockquote>
<p>下例定义了一个名为<code>Togglable</code>,含有一个<code>toggle</code>方法的协议.通过名称猜测,<code>toggle</code>方法应该是用来 <strong>切换或恢复</strong> 某个属性的状态使用的.<code>toggle</code>方法前含有<code>mutating</code>关键字,用以标识其可以更改其<code>遵循者</code>的实例及其属性的所属类型.</p>
<pre><code>protocol Togglable {
mutating func toggle()
}
</code></pre><p>如果你使用枚举或结构体来实现<code>Togglabl</code>协议时,必须在枚举或接头体的<code>toggle</code>方法前加上<code>mutating</code>关键字.</p>
<p>下例定义了一个名为<code>OnOffSwitch</code>的枚举. 这个枚举可以切换<code>On</code>,<code>Off</code>两种状态. 该枚举中的 <code>toggle</code>含有<code>mutating</code>标记,用以匹配<code>Togglable</code>协议的方法要求:</p>
<pre><code>enum OnOffSwitch: Togglable {
case Off, On
mutating func toggle() {
switch self {
case Off:
self = On
case On:
self = Off
}
}
}
var lightSwitch = OnOffSwitch.Off
lightSwitch.toggle()
//lightSwitch 现在的值为 .On
</code></pre><h2 id="-">协议作为类型</h2>
<p>尽管<code>协议</code>本身不实现任何功能,但你可以将它当做<code>类型</code>来使用.</p>
<p>包括: </p>
<ul>
<li>作为函数,方法或构造器中的参数类型,返回值类型</li>
<li>作为常量,变量,属性的类型</li>
<li>作为数组,字典或其他容器中的元素类型</li>
</ul>
<blockquote>
<p>Note: 协议是一种类型,因此你应该向其他类型那样(Int,Double,String),使用驼峰式写法来书写协议</p>
</blockquote>
<p>这里有一个使用协议类型的例子:</p>
<pre><code>class Dice {
let sides: Int
let generator: RandomNumberGenerator
init(sides: Int, generator: RandomNumberGenerator) {
self.sides = sides
self.generator = generator
}
func roll() -&gt; Int {
return Int(generator.random() * Double(sides)) +1
}
}
</code></pre><p>这里定义了一个名为 <code>Dice</code>的类,用来代表桌游中的N个面的骰子.</p>
<p> <code>Dice</code>拥有名为<code>sides</code><code>generator</code>的两个属性,前者用来表示骰子有几个面,后者用来为骰子提供一个随机数的生成器</p>
<p><code>generator</code>是一个<code>RandomNumberGenerator</code>协议类型的属性.因此,你可以为它赋值任何<code>遵循</code>该协议的类型.</p>
<p><code>Dice</code>也拥有一个<code>构造器(initializer)</code>用来设置它的初始状态.构造器中含有一个名为<code>generator</code>,类型为<code>RandomNumberGenerator</code>的形参.你可以在此传入任意遵循<code>RandomNumberGenerator</code>协议的类型.</p>
<p><code>roll</code>是一个用以返回骰子面值的实例方法.该方法先调用<code>generator</code><code>random</code>方法来创建一个 [0-1] 之间的随机数,然后使用这个随机数来生成骰子的面值. 这里的<code>generator</code> 被声明为采纳了<code>RandomNumberGenerator</code>协议,用以确保<code>random</code>方法能够被调用 </p>
<p>下例展示了一个使用<code>LinearCongruentialGenerator</code>实例作为随机数生成器的六面骰子</p>
<pre><code>var d6 = Dice(sides: 6,generator: LinearCongruentialGenerator())
for _ in 1...5 {
println(&quot;Random dice roll is \(d6.roll())&quot;)
}
//输出结果
//Random dice roll is 3
//Random dice roll is 5
//Random dice roll is 4
//Random dice roll is 5
//Random dice roll is 4
</code></pre><h2 id="-">委托(代理)</h2>
<p>委托是一种设计模式(<em>译者注:想起了那年 UITableViewDelegate 中的奔跑,那是我逝去的Objective-C...</em>),它允许类或结构体将一些需要它们负责的功能或任务交由(委托)给其他的类型.</p>
<p>代理设计模式的实现很简单,首先定义一个<code>协议</code><code>封装</code>那些需要被委托的功能的<code>函数和方法</code>, 然后确保其<code>遵循者</code>拥有这些被委托的<code>函数和方法</code>.
委托模式可以用来响应特定的动作,或接收外部数据源提供的数据而无需要知道外部数据源的类型.</p>
<p>下边这个例子展示了两个基于骰子游戏的两个协议: </p>
<pre><code>protocol DiceGame {
var dice: Dice { get }
func play()
}
protocol DiceGameDelegate {
func gameDidStart(game: DiceGame)
func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll:Int)
func gameDidEnd(game: DiceGame)
}
</code></pre><p><code>DiceGame</code>协议可以被任何包含骰子的游戏采纳.<code>DiceGameDelegate</code>协议可以用来追踪<code>DiceGame</code>的游戏过程</p>
<p>下边是一个 <code>Snakes and Ladders</code> 游戏的新版本(<a href="2">Control Flow</a><em>含有关于该游戏的介绍</em>).新版本使用<code>Dice</code>中的骰子,实现<code>DiceGame</code><code>DiceGameDelegate</code>协议</p>
<pre><code>class SnakesAndLadders: DiceGame {
let finalSquare = 25
let dic = Dice(sides: 6, generator: LinearCongruentialGenerator())
var square = 0
var board: Int[]
init() {
board = Int[](count: finalSquare + 1, repeatedValue: 0)
board[03] = +08; board[06] = +11; borad[09] = +09; board[10] = +02
borad[14] = -10; board[19] = -11; borad[22] = -02; board[24] = -08
}
var delegate: DiceGameDelegate?
func play() {
square = 0
delegate?.gameDidStart(self)
gameLoop: while square != finalSquare {
let diceRoll = dice.roll()
delegate?.game(self,didStartNewTurnWithDiceRoll: diceRoll)
switch square + diceRoll {
case finalSquare:
break gameLoop
case let newSquare where newSquare &gt; finalSquare:
continue gameLoop
default:
square += diceRoll
square += board[square]
}
}
delegate?.gameDIdEnd(self)
}
}
</code></pre><p>更详细的<code>Shakes and Ladders</code>游戏描述,请在 <a href="3">Control Flow -&gt; Break</a> 章节查看.<br>这个版本的游戏被包装到了名为<code>SnakeAndLadders</code>并实现了<code>DiceGame</code>协议的类中. 该类含有一个可读的<code>dice</code>属性和一个<code>play</code>方法用来遵循协议.</p>
<p>游戏的初始化设置(<code>setup</code>)被为类的构造器(<code>init()</code>)来实现.所有的游戏逻辑被转移到了协议方法<code>play</code>中.</p>
<p>注意:<code>delegate</code> 被定义为遵循<code>DiceGameDelegate</code>协议的可选属性,因为委托并不是该游戏的必备条件.</p>
<p><code>DicegameDelegate</code> 提供了三个方法用来追踪游戏过程.被放置于游戏的逻辑中,即<code>play()</code>方法内.分别在游戏开始时,新一轮开始时,游戏结束时被调用.</p>
<p>因为<code>delegate</code>是一个遵循<code>DiceGameDelegate</code>的可选属性,因此在<code>play()</code>方法中使用了<code>可选链</code>来调用委托方法. 如果<code>delegate</code>属性为<code>nil</code>, 则委托调用<em>优雅的,不含错误的</em>失败.如果<code>delegate</code>不为<code>nil</code>, 则这些委托方法被调用,并且把<code>SnakesAndLadders</code>的这个实例当做参数一并传递</p>
<p>下边的这个例子展示了一个名为<code>DiceGameTracker</code>,实现<code>DiceGameDelegate</code>协议的类</p>
<pre><code>class DiceGameTracker: DiceGameDelegate {
var numberOfTurns = 0
func gameDidStart(game: DiceGame) {
numberOfTurns = 0
if game is SnakesAndLadders {
println(&quot;Started a new game of Snakes and Ladders&quot;)
}
println(&quot;The game is using a \(game.dice.sides)-sided dice&quot;)
}
func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
++numberOfTurns
println(&quot;Rolled a \(diceRoll)&quot;)
}
func gameDidEnd(game: DiceGame) {
println(&quot;The game lasted for \(numberOfTurns) turns&quot;)
}
}
</code></pre><p><code>DiceGameTracker</code>实现了<code>DiceGameDelegate</code>协议中要求的全部方法.用来记录游戏已经进行的轮数. 当游戏开始时,<code>numberOfTurns</code>属性被赋值为0; 在每新一轮中递加; 游戏结束后,输出打印游戏的总轮数.</p>
<p><code>gameDidStart</code>使用<code>game</code>参数来打印游戏的一些介绍信息.<code>game</code>的类型是<code>DiceGame</code>而不是 <code>SnakeAndLadders</code>, 因此<code>gameDidStart</code>只能访问和使用<code>DiceGame</code>协议中的成员. 但是仍然可以使用类型转换来访问其实例. 在<code>gameDidStart</code>中,当<code>game</code><code>SnakesAndLadders</code>的实例时,会打印出适当的信息. 因为<code>game</code>是被视为遵循了<code>DiceGame</code>协议的属性,也就是说它拥有<code>dice</code>属性,所以<code>gameDidStart</code>方法可以访问和打印<code>dice</code><code>sides</code>属性,而无需知道这是一场什么游戏....</p>
<p>这是<code>DiceGameTracker</code>的运行实例:</p>
<pre><code>“let tracker = DiceGameTracker()
let game = SnakesAndLadders()
game.delegate = tracker
game.play()
// Started a new game of Snakes and Ladders
// The game is using a 6-sided dice
// Rolled a 3
// Rolled a 5
// Rolled a 4
// Rolled a 5
// The game lasted for 4 turns”
</code></pre><h2 id="-extension-">在延展(Extension)中添加协议成员</h2>
<p>即使无法修改源代码,依然可以通过<code>延展(Extension)</code>来扩展已存在类型(<em>译者注: 类,结构体,枚举等</em>).<code>延展</code>中可以为已存在的类型添加属性,方法,下标,协议等成员. 详情请在<a href="4">延展</a>章节中查看.</p>
<blockquote>
<p>笔记: 通过延展为已存在的类型增加协议时,该类型的实例会自动添加协议中的方法</p>
</blockquote>
<p>下例中<code>TextRepresentable</code>协议含有一个<code>asText</code> 方法,可以被任何类型<code>遵循</code></p>
<pre><code>protocol TextRepresentable {
func asText() -&gt; String
}
</code></pre><p>通过延展为为上一节中的<code>Dice</code>类实现并遵循<code>TextRepresentable</code>协议</p>
<pre><code>extension Dice: TextRepresentable {
cun asText() -&gt; String {
return &quot;A \(sides)-sided dice&quot;
}
}
</code></pre><p><code>Dice</code>类型的实例现在可以被视为<code>TextRepresentable</code>类型:</p>
<pre><code>let d12 = Dice(sides: 12,generator: LinearCongruentialGenerator())
println(d12.asText())
// 输出 &quot;A 12-sided dice&quot;
</code></pre><p><code>SnakesAndLadders</code> 类也可通过<code>延展</code>来遵循协议:</p>
<pre><code>extension SnakeAndLadders: TextRepresentable {
func asText() -&gt; String {
return &quot;A game of Snakes and Ladders with \(finalSquare) squares&quot;
}
}
println(game.asText())
// 输出 &quot;A game of Snakes and Ladders with 25 squares&quot;
</code></pre><h2 id="-">通过延展声明协议</h2>
<p>如果一个类型已经实现了协议中的所有要求,却没有声明时,可以通过声明空<code>延展</code>来采纳协议:</p>
<pre><code>struct Hamster {
var name: String
func asText() -&gt; String {
return &quot;A hamster named \(name)&quot;
}
}
extension Hamster: TextRepresentabl {}
</code></pre><p>现在开始,<code>Hamster</code>的实例可以被当做<code>TextRepresentable</code>类型使用</p>
<pre><code>let simonTheHamster = Hamster(name: &quot;Simon&quot;)
let somethingTextRepresentable: TextRepresentabl = simonTheHamester
println(somethingTextRepresentable.asText())
// 输出 &quot;A hamster named Simon&quot;
</code></pre><blockquote>
<p>注意: 类型不会因为满足了某协议而直接改变,你必须为它做出明显的实现协议声明</p>
</blockquote>
<h2 id="-">集合中的协议类型</h2>
<p>协议类型可以被集合使用,表示集合中的元素均为协议类型:</p>
<pre><code>let things: TextRepresentable[] = [game,d12,simoTheHamster]
</code></pre><p><code>things</code>数组可以被直接遍历,并调用其中元素的<code>asText()</code>函数:</p>
<pre><code>for thing in things {
println(thing.asText())
}
// A game of Snakes and Ladders with 25 squares
// A 12-sided dice
// A hamster named Simon
</code></pre><p>上文代码中,<code>thing</code>被认为是<code>TextRepresentable</code>类型而不是<code>Dice</code>,<code>DiceGame</code>,<code>Hamster</code>等类型.因此,可以在循环中调用它们的<code>asText</code>方法</p>
<h2 id="-">协议的继承</h2>
<p>协议可以通过继承一个或多个其他协议.继承协议的语法和继承类的语法相似,多个协议间用逗号<code>,</code>分隔</p>
<pre><code>protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
// 协议定义
}
</code></pre><p>下边是一个继承了<code>TextRepresentable</code>的协议</p>
<pre><code>protocol PrettyTextRepresentable: TextRepresentable {
func asPrettyText() -&gt; String
}
</code></pre><p><code>PrettyTextRepresentable</code>协议继承自<code>TextRepresentable</code>协议.任何实现<code>PrettyTextRepresentable</code>协议的类型,也需要<code>遵循</code>TextRepresentable`协议.</p>
<p>用延展为<code>SnakesAndLadders</code>遵循<code>PrettyTextRepresentable</code>协议:</p>
<pre><code>extension SnakesAndLadders: PrettyTextRepresentable {
func asPrettyText() -&gt; String {
var output = asText() + &quot;:\n&quot;
for index in 1...finalSquare {
switch board[index] {
case let ladder where ladder &gt; 0:
output += &quot;&quot;
case let snake where snake &lt; 0:
output += &quot;&quot;
default:
output += &quot;&quot;
}
}
return output
}
}
</code></pre><p>上边的延展为<code>SnakesAndLadders</code>遵循了<code>PrettyTextRepresentabel</code>协议.在<code>for in</code>中迭代出了<code>board</code>数组中的每一个元素:</p>
<ul>
<li>当数组中元素的值大于0时,用<code></code>表示</li>
<li>当数组中元素的值小于0时,用<code></code>表示</li>
<li>当数组中元素的值等于0时,用<code></code>表示</li>
</ul>
<p>任意<code>SankesAndLadders</code>的实例都可以使用<code>asPrettyText()</code>方法.</p>
<pre><code>println(game.asPrettyText())
// A game of Snakes and Ladders with 25 squares:
// ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○
</code></pre><h2 id="-">协议合成</h2>
<p>一个协议可由多个协议组成,称为<code>协议合成(protocol composition)</code>,采用<code>protocol&lt;SomeProtocol, AnotherProtocol&gt;</code>这样的语法.当有多个协议时,中间以<code>,</code>分隔.</p>
<p>举个栗子:</p>
<pre><code>protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
struct Person: Named, Aged {
var name: String
var age: Int
}
func wishHappyBirthday(celebrator: protocol&lt;Named, Aged&gt;) {
println(&quot;Happy birthday \(celebrator.name) - you&#39;re \(celebrator.age)!&quot;)
}
let birthdayPerson = Person(name: &quot;Malcolm&quot;, age: 21)
wishHappyBirthday(birthdayPerson)
// 输出 &quot;Happy birthday Malcolm - you&#39;re 21!
</code></pre><p>上例中,<code>Named</code>协议中含有<code>String</code>类型的<code>name</code>属性;<code>Aged</code>协议中含有<code>Int</code>类型的<code>age</code>属性.<code>Person</code>结构体<code>遵循</code>了这两个协议.</p>
<p>此外还定义了<code>wishHappyBirthday</code>函数,该函数的形参<code>celebrator</code>的类型为<code>protocol&lt;Named,Aged&gt;</code>,也就是说可以接受任意<code>遵循</code>了这两个协议的<code>类型</code>.</p>
<blockquote>
<p>笔记: <code>协议合成</code>并不会生成一个新协议,而是将多个协议合成为一个临时的协议.</p>
</blockquote>
<h2 id="-">检验协议的一致性</h2>
<p>使用<code>is</code><code>as</code>可以检验协议一致性,也可以将协议转换为特定的其他协议类型.检验与转换的语法和之前相同(<em>详情查看<a href="5">Typy Casting章节</a></em>):</p>
<ul>
<li><code>is</code>操作符用来检查实例是否<code>遵循</code>了某个<code>协议</code>. </li>
<li><code>as?</code>返回一个可选值,当实例<code>遵循</code>协议时,返回该协议类型;否则返回<code>nil</code></li>
<li><p><code>as</code>可以用来强制向下转型.</p>
<p> @objc protocol HasArea {</p>
<pre><code> var area: Double { get }
</code></pre><p> }</p>
</li>
</ul>
<blockquote>
<p>笔记: <code>@objc</code>用来表示协议是可选的,也可以用来表示暴露给<code>Objective-C</code>的代码,在<em>[Using Siwft with Cocoa and Objectivei-c]</em>(6)一节中有详细介绍.
<code>@objc</code>型协议只对<code></code>有效,因此只能在<code></code>中检查协议的一致性.</p>
</blockquote>
<pre><code>class Circle: HasArea {
let pi = 3.1415927
var radius: Double
var area: Double { return pi * radius * radius }
init(radius: Double) { self.radius = radius }
}
class Country: HasArea {
var area: Double
init(area: Double) { self.area = area }
}
</code></pre><p><code>Circle</code><code>Country</code>都遵循了<code>HasArea</code>协议,前者把<code>area</code>写为<code>计算型属性</code>,后者则把<code>area</code>写为<code>存储型属性</code></p>
<p>下边是一个没事实现<code>HasArea</code>协议的<code>Animal</code>类:</p>
<pre><code>class Animal {
var legs: Int
init(legs: Int) { self.legs = legs }
}
</code></pre><p><code>Circle,Country,Animal</code>并没有一个相同的基础类,可以使用<code>AnyObject</code>类型的数组来装在他们的实例:</p>
<pre><code>let objects: AnyObject[] = [
Circle(radius: 2.0),
Country(area: 243_610),
Animal(legs: 4)
]
</code></pre><p>在迭代时可以检查<code>object</code>数组的元素是否<code>遵循</code><code>HasArea</code>协议:</p>
<pre><code>for object in objects {
if let objectWithArea = object as? HasArea {
println(&quot;Area is \(objectWithArea.area)&quot;)
} else {
println(&quot;Something that doesn&#39;t have an area&quot;)
}
}
// Area is 12.5663708
// Area is 243610.0
// Something that doesn&#39;t have an area
</code></pre><p>当数组中的元素遵循<code>HasArea</code>协议时,通过<code>as?</code>操作符将其<code>可选绑定(optional binding)</code><code>objectWithArea</code>常量上.</p>
<p><code>objects</code>数组中元素的类型并不会被改变,但是当它们被赋值给<code>objectWithArea</code>时只被视为<code>HasArea</code>类型,并且只有<code>area</code>属性可以被访问.</p>
<h2 id="-">可选协议要求</h2>
<p>可选协议含有可选成员,其<code>遵循者</code>可以选择是否实现这些成员.在协议中使用<code>@optional</code>关键字作为前缀来定义可选成员.</p>
<p>可选协议在调用时使用<code>可选链</code>,详细内容在<a href="7">Optional Chaning</a>章节中查看.</p>
<p><code>someOptionalMethod?(someArgument)</code>一样,你可以在可选方法名称后加上<code>?</code>来检查该方法是否被实现.<code>可选方法</code><code>可选属性</code>都会返回一个<code>可选值(optional value)</code>,当其不可访问时,<code>?</code>之后语句不会执行,并返回<code>nil</code></p>
<blockquote>
<p>笔记: 可选协议只能在含有<code>@objc</code>前缀的协议中生效.且<code>@objc</code>的协议只能被<code></code>遵循</p>
</blockquote>
<p>下问定义了整型计数器<code>Counter</code>类,该类使用外部的数据源来提供<code>增量值(increment amount)</code>. 数据源定义为<code>CounterDataSource</code>类型的协议,如下所示</p>
<pre><code>@objc protocol CounterDataSource {
@optional func incrementForCount(count: Int) -&gt; Int
@optional var fixedIncrement: Int { get }
}
</code></pre><p><code>CounterDataSource</code>含有<code>incrementForCount</code><code>可选方法</code><code>fiexdIncrement</code><code>可选属性</code>.</p>
<blockquote>
<p>笔记: <code>CounterDataSource</code>中的属性和方法都是可选的,因此可以不提供所需要的属性或方法来实现它.尽管技术上允许,但这并不提倡这样用.</p>
</blockquote>
<p><code>Counter</code>类的定义在下边,它含有一个名为<code>dataSource</code>,<code>CounterDataSource?</code>类型的可选属性:</p>
<pre><code>@objc class Counter {
var count = 0
var dataSource: CounterDataSource?
func increment() {
if let amount = dataSource?.incrementForCount?(count) {
count += amount
} else if let amount = dataSource?.fixedIncrement? {
count += amount
}
}
}
</code></pre><p><code>count</code>属性用于存储当前的值,<code>increment</code>方法用来为<code>count</code>赋值.</p>
<p><code>increment</code>方法通过<code>可选链</code>,尝试从两种<code>可选成员</code>中获取<code>count</code>.</p>
<ol>
<li>由于<code>dataSource</code>可能为<code>nil</code>,因此在<code>dataSource</code>后边加上了<code>?</code>标记来表明只在<code>dataSource</code>非空时才去调用incrementForCount`方法.</li>
<li>即使<code>dataSource</code>存在,但是也无法保证其是否实现了<code>incrementForCount</code>方法,因此在<code>incrementForCount</code>方法后边也加有<code>?</code>标记</li>
</ol>
<p>在调用<code>incrementForCount</code>方法后,<code>Int</code><code>可选值</code>通过<code>可选绑定(optional binding)</code>自动拆包并赋值给常量<code>amount</code>.</p>
<p><code>incrementForCount</code>不能被调用时,尝试使用<code>可选属性``fixedIncrement</code>来代替.</p>
<p>下边是一个简单的<code>CounterDataSource</code>协议的实现.</p>
<pre><code>class ThreeSource: CounterDataSource {
let fixedIncrement = 3
}
</code></pre><p>可以使用<code>ThreeSource</code>作为数据源开实例化一个<code>Counter</code>:</p>
<pre><code>var counter = Counter()
counter.dataSource = ThreeSource()
for _ in 1...4 {
counter.increment()
println(counter.count)
}
// 3
// 6
// 9
// 12
</code></pre><p>下边是一个更为复杂的数据源实现:</p>
<pre><code>class TowardsZeroSource: CounterDataSource {
func incrementForCount(count: Int) -&gt; Int {
if count == 0 {
return 0
} else if count &lt; 0 {
return 1
} else {
return -1
}
}
}
</code></pre><p><code>TowardZeroSource</code>类实现了<code>CounterDataSource</code><code>可选方法``incrementForCount</code>.</p>
<p>下边是执行的代码:</p>
<pre><code>counter.count = -4
counter.dataSource = TowardsZeroSource()
for _ in 1...5 {
counter.increment()
println(counter.count)
}
// -3
// -2
// -1
// 0
// 0
</code></pre>
</section>
</div>
</div>
</div>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.22" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.22" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_40">
<section class="normal" id="section-gitbook_45">
<h1 id="-">泛型</h1>
<hr>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.23" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2.23" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="2" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_44">
<section class="normal" id="section-gitbook_49">
<h1 id="swift-">Swift 教程</h1>
<p>本章介绍了 Swift 的各种特性及其使用方法,是全书的核心部分。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="3.1" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="3.1" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_46">
<section class="normal" id="section-gitbook_51">
<h1 id="-">关于语言附注</h1>
<p>本书的这一节描述了Swift编程语言的形式语法。这里描述的语法是为了帮助您更详细的了解该语言而不是让您直接实现一个解析器或编译器。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="3.2" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="3.2" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,6 +587,199 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_56">
<h1 id="-">语法结构</h1>
<p>本页包含内容:</p>
<ul>
<li>空白与注释(<em>Whitespace and Comments</em></li>
<li>标识符(<em>Identifiers</em></li>
<li>关键字(<em>Keywords</em></li>
<li>字面量(<em>Literals</em></li>
<li>运算符(<em>Operators</em></li>
</ul>
<p>Swift 的“语法结构(<em>lexical structure</em>)”描述了如何在该语言中用字符序列构建合法标记,组成该语言中最底层的代码块,并在之后的章节中用于描述语言的其他部分。</p>
<p>通常,标记在随后介绍的语法约束下,由 Swift 源文件的输入文本中提取可能的最长子串生成。这种方法称为“最长匹配项(<em>longest match</em>)”,或者“最大适合”(<em>maximal munch</em>)。</p>
<h2 id="-">空白与注释</h2>
<p>空白(<em>whitespace</em>)有两个用途:分隔源文件中的标记和区分运算符属于前缀还是后缀,(参见 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-XID_871" target="_blank">运算符</a>)在其他情况下则会被忽略。以下的字符会被当作空白:空格(<em>space</em>U+0020、换行符<em>line feed</em>U+000A、回车符<em>carriage return</em>U+000D、水平 tab<em>horizontal tab</em>U+0009、垂直 tab<em>vertical tab</em>U+000B、换页符<em>form feed</em>U+000C以及空<em>null</em>U+0000</p>
<p>注释(<em>comments</em>)被编译器当作空白处理。单行注释由 <code>//</code> 开始直到该行结束。多行注释由 <code>/*</code> 开始,以 <code>*/</code> 结束。可以嵌套注释,但注意注释标记必须匹配。</p>
<h2 id="-">标识符</h2>
<p>标识符(<em>identifiers</em>)可以由以下的字符开始:大写或小写的字母 <code>A</code><code>Z</code>、下划线 <code>_</code>、基本多语言面(<em>Basic Multilingual Plane</em>)中的 Unicode 非组合字符以及基本多语言面以外的非专用区(<em>Private Use Area</em>)字符。首字符之后,标识符允许使用数字和 Unicode 字符组合。</p>
<p>使用保留字(<em>reserved word</em>)作为标识符,需要在其前后增加反引号 <code>`</code>。例如,<code>class</code> 不是合法的标识符,但可以使用 <code>`class`</code>。反引号不属于标识符的一部分,<code>`x`</code><code>x</code> 表示同一标识符。</p>
<p>闭包(<em>closure</em>)中如果没有明确指定参数名称,参数将被隐式命名为 <code>$0</code><code>$1</code><code>$2</code>... 这些命名在闭包作用域内是合法的标识符。</p>
<blockquote>
<p>标识符语法</p>
<p><em>identifier</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-head" target="_blank">identifier-head­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-characters" target="_blank">identifier-characters</a>­ <em>opt</em></p>
<p><em>identifier</em> → `­ <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-head" target="_blank">identifier-head­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-characters" target="_blank">identifier-characters­</a> <em>opt­</em> `­</p>
<p><em>identifier</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/implicit-parameter-name" target="_blank">implicit-parameter-name­</a></p>
<p><em>identifier-list</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier" target="_blank">identifier­</a> | <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier" target="_blank">identifier­</a> , <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-list" target="_blank">­identifier-list</a>­</p>
<p><em>identifier-head</em> → A 到 Z 大写或小写字母</p>
<p><em>identifier-head</em> → U+00A8, U+00AA, U+00AD, U+00AF, U+00B2U+00B5, 或 U+00B7U+00BA</p>
<p><em>identifier-head</em> → U+00BCU+00BE, U+00C0U+00D6, U+00D8U+00F6, 或 U+00F8U+00FF</p>
<p><em>identifier-head</em> → U+0100U+02FF, U+0370U+167F, U+1681U+180D, 或 U+180FU+1DBF</p>
<p><em>identifier-head</em> → U+1E00U+1FFF</p>
<p><em>identifier-head</em> → U+200BU+200D, U+202AU+202E, U+203FU+2040, U+2054, 或 U+2060U+206F</p>
<p><em>identifier-head</em> → U+2070U+20CF, U+2100U+218F, U+2460U+24FF, 或 U+2776U+2793</p>
<p><em>identifier-head</em> → U+2C00U+2DFF 或 U+2E80U+2FFF</p>
<p><em>identifier-head</em> → U+3004U+3007, U+3021U+302F, U+3031U+303F, 或 U+3040U+D7FF</p>
<p><em>identifier-head</em> → U+F900U+FD3D, U+FD40U+FDCF, U+FDF0U+FE1F, 或 U+FE30U+FE44</p>
<p><em>identifier-head</em> → U+FE47U+FFFD</p>
<p><em>identifier-head</em> → U+10000U+1FFFD, U+20000U+2FFFD, U+30000U+3FFFD, 或 U+40000U+4FFFD</p>
<p><em>identifier-head</em> → U+50000U+5FFFD, U+60000U+6FFFD, U+70000U+7FFFD, 或 U+80000U+8FFFD</p>
<p><em>identifier-head</em> → U+90000U+9FFFD, U+A0000U+AFFFD, U+B0000U+BFFFD, 或 U+C0000U+CFFFD</p>
<p><em>identifier-head</em> → U+D0000U+DFFFD 或 U+E0000U+EFFFD</p>
<p><em>identifier-character</em> → 数字 0 到 9</p>
<p><em>identifier-character</em> → U+0300U+036F, U+1DC0U+1DFF, U+20D0U+20FF, or U+FE20U+FE2F</p>
<p><em>identifier-character</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-head" target="_blank">identifier-head­</a></p>
<p><em>identifier-characters</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-character" target="_blank">identifier-character</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-characters" target="_blank">­identifier-characters­</a> <em>opt­</em></p>
<p><em>implicit-parameter-name</em><strong>$­</strong> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-digits" target="_blank">decimal-digits­</a></p>
</blockquote>
<h2 id="-">关键字</h2>
<p>被保留的关键字(<em>keywords</em>)不允许用作标识符,除非被反引号转义,参见 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-XID_796" target="_blank">标识符</a></p>
<ul>
<li><p><strong>用作声明的关键字:</strong> <em>class</em><em>deinit</em><em>enum</em><em>extension</em><em>func</em><em>import</em><em>init</em><em>let</em><em>protocol</em><em>static</em><em>struct</em><em>subscript</em><em>typealias</em><em>var</em> </p>
</li>
<li><p><strong>用作语句的关键字:</strong> <em>break</em><em>case</em><em>continue</em><em>default</em><em>do</em><em>else</em><em>fallthrough</em><em>if</em><em>in</em><em>for</em><em>return</em><em>switch</em><em>where</em><em>while</em></p>
</li>
<li><p><strong>用作表达和类型的关键字:</strong> <em>as</em><em>dynamicType</em><em>is</em><em>new</em><em>super</em><em>self</em><em>Self</em><em>Type</em><em>__COLUMN__</em><em>__FILE__</em><em>__FUNCTION__</em><em>__LINE__</em></p>
</li>
<li><p><strong>特定上下文中被保留的关键字:</strong> <em>associativity</em><em>didSet</em><em>get</em><em>infix</em><em>inout</em><em>left</em><em>mutating</em><em>none</em><em>nonmutating</em><em>operator</em><em>override</em><em>postfix</em><em>precedence</em><em>prefix</em><em>right</em><em>set</em><em>unowned</em><em>unowned(safe)</em><em>unowned(unsafe)</em><em>weak</em><em>willSet</em>,这些关键字在特定上下文之外可以被用于标识符。</p>
</li>
</ul>
<h2 id="-">字面量</h2>
<p>字面值表示整型、浮点型数字或文本类型的值,举例如下:</p>
<pre><code>42 // 整型字面量
3.14159 // 浮点型字面量
&quot;Hello, world!&quot; // 文本型字面量
</code></pre><blockquote>
<p>字面量语法</p>
<p><em>literal</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/integer-literal" target="_blank">integer-literal­</a> | <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/floating-point-literal" target="_blank">floating-point-literal</a>­ | <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/string-literal" target="_blank">string-literal­</a></p>
</blockquote>
<h3 id="-">整型字面量</h3>
<p>整型字面量(<em>integer literals</em>)表示未指定精度整型数的值。整型字面量默认用十进制表示,可以加前缀来指定其他的进制,二进制字面量加 <code>0b</code>,八进制字面量加 <code>0o</code>,十六进制字面量加 <code>0x</code></p>
<p>十进制字面量包含数字 <code>0</code><code>9</code>。二进制字面量只包含 <code>0</code><code>1</code>,八进制字面量包含数字 <code>0</code><code>7</code>,十六进制字面量包含数字 <code>0</code><code>9</code> 以及字母 <code>A</code><code>F</code> (大小写均可)。</p>
<p>负整数的字面量在数字前加减号 <code>-</code>,比如 <code>-42</code></p>
<p>允许使用下划线 <code>_</code> 来增加数字的可读性,下划线不会影响字面量的值。整型字面量也可以在数字前加 <code>0</code>,同样不会影响字面量的值。</p>
<pre><code>1000_000 // 等于 1000000
005 // 等于 5
</code></pre><p>除非特殊指定,整型字面量的默认类型为 Swift 标准库类型中的 <code>Int</code>。Swift 标准库还定义了其他不同长度以及是否带符号的整数类型,请参考 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_411" target="_blank">整数类型</a></p>
<blockquote>
<p>整型字面量语法</p>
<p><em>integer-literal</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/binary-literal" target="_blank">binary-literal­</a></p>
<p><em>integer-literal</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-literal" target="_blank">octal-literal­</a></p>
<p><em>integer-literal</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal" target="_blank">decimal-literal­</a></p>
<p><em>integer-literal</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal" target="_blank">hexadecimal-literal</a>­</p>
<p><em>binary-literal</em><strong>0b</strong>­ <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/binary-digit" target="_blank">binary-digit</a> ­<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/binary-literal-characters" target="_blank">binary-literal-characters­</a> <em>opt­</em></p>
<p><em>binary-digit</em> → 数字 0 或 1</p>
<p><em>binary-literal-character</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/binary-digit" target="_blank">binary-digit</a>­ | _­</p>
<p><em>binary-literal-characters</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/binary-literal-character" target="_blank">binary-literal-character</a> ­<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/binary-literal-characters" target="_blank">binary-literal-characters­</a> <em>opt­</em></p>
<p><em>octal-literal</em><strong>0o</strong>­ <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-digit" target="_blank">octal-digit</a> ­<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-literal-characters" target="_blank">octal-literal-characters­</a> <em>opt­</em></p>
<p><em>octal-digit</em> → 数字 0 至 7</p>
<p><em>octal-literal-character</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-digit" target="_blank">octal-digit</a>­ | _­</p>
<p><em>octal-literal-characters</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-literal-character" target="_blank">octal-literal-character</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-literal-characters" target="_blank">­octal-literal-characters­</a> <em>opt­</em></p>
<p><em>decimal-literal</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-digit" target="_blank">decimal-digit</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal-characters" target="_blank">­decimal-literal-characters­</a> <em>opt­</em></p>
<p><em>decimal-digit</em> → 数字 0 至 9</p>
<p><em>decimal-digits</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-digit" target="_blank">decimal-digit­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-digits" target="_blank">decimal-digits­</a> <em>opt­</em></p>
<p><em>decimal-literal-character</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-digit" target="_blank">decimal-digit­</a> | _­</p>
<p><em>decimal-literal-characters</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal-character" target="_blank">decimal-literal-character</a> ­<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal-characters" target="_blank">decimal-literal-characters­</a> <em>opt­</em></p>
<p><em>hexadecimal-literal</em><strong>0x</strong> ­<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal-characters" target="_blank">­hexadecimal-literal-characters­</a> <em>opt­</em></p>
<p><em>hexadecimal-digit</em> → 数字 0 到 9, a 到 f, 或 A 到 F</p>
<p><em>hexadecimal-literal-character</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit</a>­ | _­</p>
<p><em>hexadecimal-literal-characters</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal-character" target="_blank">hexadecimal-literal-character­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal-characters" target="_blank">hexadecimal-literal-characters</a> ­<em>opt­</em></p>
</blockquote>
<h3 id="-">浮点型字面量</h3>
<p>浮点型字面量(<em>floating-point literals</em>)表示未指定精度浮点数的值。</p>
<p>浮点型字面量默认用十进制表示(无前缀),也可以用十六进制表示(加前缀 <code>0x</code>)。</p>
<p>十进制浮点型字面量(<em>decimal floating-point literals</em>)由十进制数字串后跟小数部分或指数部分(或两者皆有)组成。十进制小数部分由小数点 <code>.</code> 后跟十进制数字串组成。指数部分由大写或小写字母 <code>e</code> 后跟十进制数字串组成,这串数字表示 <code>e</code> 之前的数量乘以 10 的几次方。例如:<code>1.25e2</code> 表示 <code>1.25 ⨉ 10^2</code>,也就是 <code>125.0</code>;同样,<code>1.25e2</code> 表示 <code>1.25 ⨉ 10^2</code>,也就是 <code>0.0125</code></p>
<p>十六进制浮点型字面量(<em>hexadecimal floating-point literals</em>)由前缀 <code>0x</code> 后跟可选的十六进制小数部分以及十六进制指数部分组成。十六进制小数部分由小数点后跟十六进制数字串组成。指数部分由大写或小写字母 <code>p</code> 后跟十进制数字串组成,这串数字表示 <code>p</code> 之前的数量乘以 2 的几次方。例如:<code>0xFp2</code> 表示 <code>15 ⨉ 2^2</code>,也就是 <code>60</code>;同样,<code>0xFp-2</code> 表示 <code>15 ⨉ 2^-2</code>,也就是 <code>3.75</code></p>
<p>与整型字面量不同,负的浮点型字面量由一元运算符减号 <code>-</code> 和浮点型字面量组成,例如 <code>-42.0</code>。这代表一个表达式,而不是一个浮点整型字面量。</p>
<p>允许使用下划线 <code>_</code> 来增强可读性,下划线不会影响字面量的值。浮点型字面量也可以在数字前加 <code>0</code>,同样不会影响字面量的值。</p>
<pre><code>10_000.56 // 等于 10000.56
005000.76 // 等于 5000.76
</code></pre><p>除非特殊指定,浮点型字面量的默认类型为 Swift 标准库类型中的 <code>Double</code>表示64位浮点数。Swift 标准库也定义 <code>Float</code> 类型表示32位浮点数。</p>
<blockquote>
<p>浮点型字面量语法</p>
<p><em>floating-point-literal</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal" target="_blank">decimal-literal</a> ­<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-fraction" target="_blank">decimal-fraction­</a> <em>opt</em> ­<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-exponent" target="_blank">decimal-exponent­</a> <em>opt­</em></p>
<p><em>floating-point-literal</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal" target="_blank">hexadecimal-literal</a> ­<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-fraction" target="_blank">hexadecimal-fraction</a> ­<em>opt­</em> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-exponent" target="_blank">hexadecimal-exponent</a>­</p>
<p><em>decimal-fraction</em> → . <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal" target="_blank">­decimal-literal­</a></p>
<p><em>decimal-exponent</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/floating-point-e" target="_blank">floating-point-e</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/sign" target="_blank">­sign­</a> <em>opt­</em> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal" target="_blank">decimal-literal</a>­</p>
<p><em>hexadecimal-fraction</em> → . <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal" target="_blank">­hexadecimal-literal­</a> <em>opt­</em></p>
<p><em>hexadecimal-exponent</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/floating-point-p" target="_blank">floating-point-p­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/sign" target="_blank">sign­</a> <em>opt­</em> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal" target="_blank">hexadecimal-literal­</a></p>
<p><em>floating-point-e</em><strong>e­</strong> | <strong>E</strong>­</p>
<p><em>floating-point-p</em><strong>p</strong>­ | <strong>P</strong>­</p>
<p><em>sign</em><strong>+</strong>­ | <strong>-</strong>­</p>
</blockquote>
<h3 id="-">文本型字面量</h3>
<p>文本型字面量(<em>string literal</em>)由双引号中的字符串组成,形式如下:</p>
<pre><code>&quot;characters&quot;
</code></pre><p>文本型字面量中不能包含未转义的双引号 <code>&quot;</code>、未转义的反斜线<code>\</code>、回车符(<em>carriage return</em>)或换行符(<em>line feed</em>)。</p>
<p>可以在文本型字面量中使用的转义特殊符号如下:</p>
<ul>
<li>空字符Null Character<code>\0</code></li>
<li>反斜线Backslash<code>\\</code></li>
<li>水平 Tab Horizontal Tab<code>\t</code></li>
<li>换行符Line Feed<code>\n</code></li>
<li>回车符Carriage Return<code>\r</code></li>
<li>双引号Double Quote<code>\&quot;</code></li>
<li>单引号Single Quote<code>\&#39;</code></li>
</ul>
<p>字符也可以用以下方式表示:</p>
<ul>
<li><code>\x</code> 后跟两位十六进制数字</li>
<li><code>\u</code> 后跟四位十六进制数字</li>
<li><code>\U</code> 后跟八位十六进制数字</li>
</ul>
<p>后跟的数字表示一个 Unicode 码点。</p>
<p>文本型字面量允许在反斜线小括号 <code>\()</code> 中插入表达式的值。插入表达式(<em>interpolated expression</em>)不能包含未转义的双引号 <code>&quot;</code>、反斜线 <code>\</code>、回车符或者换行符。表达式值的类型必须在 <em>String</em> 类中有对应的初始化方法。</p>
<p>例如,以下所有文本型字面量的值相同:</p>
<pre><code>&quot;1 2 3&quot;
&quot;1 2 \(3)&quot;
&quot;1 2 \(1 + 2)&quot;
var x = 3; &quot;1 2 \(x)&quot;
</code></pre><p>文本型字面量的默认类型为 <code>String</code>。组成字符串的字符类型为 <code>Character</code>。更多有关 <code>String</code><code>Character</code> 的信息请参照 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-XID_368" target="_blank">字符串和字符</a></p>
<blockquote>
<p>文本型字面量语法</p>
<p><em>string-literal</em><strong>&quot;­</strong> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/quoted-text" target="_blank">quoted-text</a> <strong>­&quot;­</strong></p>
<p><em>quoted-text</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/quoted-text-item" target="_blank">quoted-text-item­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/quoted-text" target="_blank">quoted-text</a> ­<em>opt­</em></p>
<p><em>quoted-text-item</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/escaped-character" target="_blank">escaped-character­</a></p>
<p><em>quoted-text-item</em><strong>(</strong>­ <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/swift/grammar/expression" target="_blank">expression­</a> <strong>)</strong>­</p>
<p><em>quoted-text-item</em> → 除 <code>&quot;</code><code>\</code>­、<code>U+000A</code><code>U+000D</code> 以外的任何 Unicode 扩展字符集</p>
<p><em>escaped-character</em><strong>\0­</strong> | <strong>\</strong>­ | <strong>\t­</strong> | <strong>\n</strong>­ | <strong>\r­</strong> | <strong>\&quot;­</strong> | <strong>\&#39;</strong>­</p>
<p><em>escaped-character</em><strong>\x­</strong> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit</a>­ <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit­</a></p>
<p><em>escaped-character</em><strong>\u</strong> ­<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">­hexadecimal-digit</a>­ <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit­</a></p>
<p><em>escaped-character</em><strong>\U­</strong> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit" target="_blank">hexadecimal-digit­</a></p>
</blockquote>
<h2 id="-">运算符</h2>
<p>Swift 标准库定义了许多可供使用的运算符,其中大部分在 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-XID_70" target="_blank">基础运算符</a><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_28" target="_blank">高级运算符</a> 中进行了阐述。这里将描述哪些字符能用作运算符。</p>
<p>运算符由一个或多个以下字符组成:
<code>/</code><code>=</code><code>-</code><code>+</code><code>!</code><code>*</code><code>%</code><code>&lt;</code><code>&gt;</code><code>&amp;</code><code>|</code><code>^</code><code>~</code><code>.</code>。也就是说,标记 <code>=</code>, <code>-&gt;</code><code>//</code><code>/*</code><code>*/</code><code>.</code> 以及一元前缀运算符 <code>&amp;</code> 属于保留字,这些标记不能被重写或用于自定义运算符。</p>
<p>运算符两侧的空白被用来区分该运算符是否为前缀运算符(<em>prefix operator</em>)、后缀运算符(<em>postfix operator</em>)或二元运算符(<em>binary operator</em>)。规则总结如下:</p>
<ul>
<li><p>如果运算符两侧都有空白或两侧都无空白,将被看作二元运算符。例如:<code>a+b</code><code>a + b</code> 中的运算符 <code>+</code> 被看作二元运算符。</p>
</li>
<li><p>如果运算符只有左侧空白,将被看作前缀一元运算符。例如 <code>a ++b</code> 中的 <code>++</code> 被看作前缀一元运算符。</p>
</li>
<li><p>如果运算符只有右侧空白,将被看作后缀一元运算符。例如 <code>a++ b</code> 中的 <code>++</code> 被看作后缀一元运算符。</p>
</li>
<li><p>如果运算符左侧没有空白并紧跟 <code>.</code>,将被看作后缀一元运算符。例如 <code>a++.b</code> 中的 <code>++</code> 被看作后缀一元运算符(同理, <code>a++ . b</code> 中的 <code>++</code> 是后缀一元运算符而 <code>a ++ .b</code> 中的 <code>++</code> 不是).</p>
</li>
</ul>
<p>鉴于这些规则,运算符前的字符 <code>(</code><code>[</code><code>{</code> ;运算符后的字符 <code>)</code><code>]</code><code>}</code> 以及字符 <code>,</code><code>;</code><code>:</code> 都将用于空白检测。</p>
<p>以上规则需注意一点,如果运算符 <code>!</code><code>?</code> 左侧没有空白,则不管右侧是否有空白都将被看作后缀运算符。如果将 <code>?</code> 用作可选类型(<em>optional type</em>)修饰,左侧必须无空白。如果用于条件运算符 <code>? :</code>,必须两侧都有空白。 </p>
<p>在特定构成中 ,以 <code>&lt;</code><code>&gt;</code> 开头的运算符会被分离成两个或多个标记,剩余部分以同样的方式会被再次分离。因此,在 <code>Dictionary&lt;String, Array&lt;Int&gt;&gt;</code> 中没有必要添加空白来消除闭合字符 <code>&gt;</code> 的歧义。在这个例子中, 闭合字符 <code>&gt;</code> 被看作单字符标记,而不会被误解为移位运算符 <code>&gt;&gt;</code></p>
<p>要学习如何自定义新的运算符,请参考 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_48" target="_blank">自定义操作符</a><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-XID_644" target="_blank">运算符声明</a>。学习如何重写现有运算符,请参考 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_43" target="_blank">运算符方法</a></p>
<blockquote>
<p>运算符语法</p>
<p><em>operator</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/operator-character" target="_blank">operator-character­</a> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/operator" target="_blank">operator­</a> <em>opt­</em></p>
<p><em>operator-character</em><strong>/­</strong> | <strong>=­</strong> | <strong>-­</strong> | <strong>+­</strong> | <strong>!­</strong> | <strong>*­</strong> | <strong>%­</strong> | <strong>&lt;­</strong> | <strong>&gt;­</strong> | <strong>&amp;­</strong> | <strong>|­</strong> | <strong>^­</strong> | <strong>~­</strong> | <strong>.­</strong></p>
<p><em>binary-operator</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/operator" target="_blank">operator­</a></p>
<p><em>prefix-operator</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/operator" target="_blank">operator­</a></p>
<p><em>postfix-operator</em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/operator" target="_blank">operator­</a></p>
</blockquote>
</section>
</div>
</div>
</div>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="3.3" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="3.3" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,6 +587,219 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_52">
<h1 id="-types-">类型Types</h1>
<hr>
<p>本页包含内容:</p>
<ul>
<li>类型标注Type Annotation</li>
<li>类型标识符Type Identifier</li>
<li>元组类型Tuple Type</li>
<li>函数类型Function Type</li>
<li>数组类型Array Type</li>
<li>可选类型Optional Type</li>
<li>隐式解析可选类型Implicitly Unwrapped Optional Type</li>
<li>协议合成类型Protocol Composition Type</li>
<li>元类型Metatype Type</li>
<li>类型继承子句Type Inheritance Clause</li>
<li>类型推断Type Inference</li>
</ul>
<p>Swift语言存在两种类型命名型类型和复合型类型。<em>命名型类型</em>是指定义时可以给定名字的类型。命名型类型包括类、结构体、枚举和协议。比如,一个用户定义的类<code>MyClass</code>的实例拥有类型<code>MyClass</code>。除了用户定义的命名型类型Swift标准库也定义了很多常用的命名型类型包括那些表示数组、字典和可选值的类型。</p>
<p>那些通常被其它语言认为是基本或初级的数据型类型Data types——比如表示数字、字符和字符串——实际上就是命名型类型Swift标准库是使用结构体定义和实现它们的。因为它们是命名型类型因此你可以按照“扩展和扩展声明”章节里讨论的那样声明一个扩展来增加它们的行为以适应你程序的需求。</p>
<p><em>复合型类型</em>是没有名字的类型它由Swift本身定义。Swift存在两种复合型类型函数类型和元组类型。一个复合型类型可以包含命名型类型和其它复合型类型。例如元组类型<code>(Int, (Int, Int))</code>包含两个元素:第一个是命名型类型<code>Int</code>,第二个是另一个复合型类型<code>(Int, Int)</code>.</p>
<p>本节讨论Swift语言本身定义的类型并描述Swift中的类型推断行为。</p>
<blockquote>
<p>类型的语法:
<em>type</em><em>array-type</em> | <em>function-type</em> | <em>type-identifier</em> | <em>tuple-type</em> | <em>optional-type</em> | <em>implicitly-unwrapped-optional-type</em> | protocol-composition-type | metatype-type</p>
</blockquote>
<h2 id="-">类型标注</h2>
<p>类型标注显式地指定一个变量或表达式的值。类型标注始于冒号<code>:</code>终于类型,比如下面两个例子:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> someTuple(Double, Double) = (<span class="hljs-number">3.14159</span>, <span class="hljs-number">2.71828</span>)
func someFunction(a: Int){ <span class="hljs-comment">/* ... */</span> }
</code></pre>
<p>在第一个例子中,表达式<code>someTuple</code>的类型被指定为<code>(Double, Double)</code>。在第二个例子中,函数<code>someFunction</code>的参数<code>a</code>的类型被指定为<code>Int</code></p>
<p>类型标注可以在类型之前包含一个类型特性type attributes的可选列表。</p>
<blockquote>
<p>类型标注的语法:
<em>type-annotation</em> → :<em>attributes</em>[opt] <em>type</em></p>
</blockquote>
<h2 id="-">类型标识符</h2>
<p>类型标识符引用命名型类型或者是命名型/复合型类型的别名。</p>
<p>大多数情况下,类型标识符引用的是同名的命名型类型。例如类型标识符<code>Int</code>引用命名型类型<code>Int</code>,同样,类型标识符<code>Dictionary&lt;String, Int&gt;</code>引用命名型类型<code>Dictionary&lt;String, Int&gt;</code></p>
<p>在两种情况下类型标识符引用的不是同名的类型。情况一,类型标识符引用的是命名型/复合型类型的类型别名。比如,在下面的例子中,类型标识符使用<code>Point</code>来引用元组<code>(Int, Int)</code></p>
<pre><code class="lang-javascript">typealias Point = (Int, Int)
<span class="hljs-keyword">let</span> origin: Point = (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)
</code></pre>
<p>情况二类型标识符使用dot(<code>.</code>)语法来表示在其它模块modules或其它类型嵌套内声明的命名型类型。例如下面例子中的类型标识符引用在<code>ExampleModule</code>模块中声明的命名型类型<code>MyType</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> someValue: ExampleModule.MyType
</code></pre>
<blockquote>
<p>类型标识符的语法:
<em>type-identifier</em><em>type-name generic-argument-clause</em>[opt] | <em>type-name generic-argument-clause</em>[opt].<em>type-identifier</em>
<em>type-name</em><em>identifier</em></p>
</blockquote>
<h2 id="-">元组类型</h2>
<p>元组类型使用逗号隔开并使用括号括起来的0个或多个类型组成的列表。</p>
<p>你可以使用元组类型作为一个函数的返回类型,这样就可以使函数返回多个值。你也可以命名元组类型中的元素,然后用这些名字来引用每个元素的值。元素的名字由一个标识符和<code>:</code>组成。“函数和多返回值”章节里有一个展示上述特性的例子。</p>
<p><code>void</code>是空元组类型<code>()</code>的别名。如果括号内只有一个元素,那么该类型就是括号内元素的类型。比如,<code>(Int)</code>的类型是<code>Int</code>而不是<code>(Int)</code>。所以,只有当元组类型包含两个元素以上时才可以标记元组元素。</p>
<blockquote>
<p>元组类型语法:
<em>tuple</em> → (<em>tuple-type-body</em>[opt])
<em>tuple-type-body</em><em>tuple-type-element-list</em> ...[opt]
<em>tuple-type-element-list</em><em>tuple-type-element</em> | <em>tuple-type-element</em>, <em>tuple-type-element-list</em>
<em>tuple-type-element</em><em>attributes</em>[opt] <strong>inout</strong> [opt] <em>type</em> | <strong>inout</strong> [opt] <em>element-name type-annotation</em>
<em>element-name</em><em>identifier</em></p>
</blockquote>
<h2 id="-">函数类型</h2>
<p>函数类型表示一个函数、方法或闭包的类型,它由一个参数类型和返回值类型组成,中间用箭头<code>-&gt;</code>隔开:</p>
<ul>
<li><code>parameter type</code> -&gt; <code>return type</code></li>
</ul>
<p>由于 <em>参数类型</em><em>返回值类型</em> 可以是元组类型,所以函数类型可以让函数与方法支持多参数与多返回值。</p>
<p>你可以对函数类型应用带有参数类型<code>()</code>并返回表达式类型的<code>auto_closure</code>属性(见类型属性章节)。一个自动闭包函数捕获特定表达式上的隐式闭包而非表达式本身。下面的例子使用<code>auto_closure</code>属性来定义一个很简单的assert函数</p>
<pre><code class="lang-javascript">func simpleAssert(condition: @auto_closure () -&gt; Bool, message: <span class="hljs-built_in">String</span>){
<span class="hljs-keyword">if</span> !condition(){
println(message)
}
}
<span class="hljs-keyword">let</span> testNumber = <span class="hljs-number">5</span>
simpleAssert(testNumber % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>, <span class="hljs-string">"testNumber isn't an even number."</span>)
<span class="hljs-comment">// prints "testNumber isn't an even number."</span>
</code></pre>
<p>函数类型可以拥有一个可变长参数作为参数类型中的最后一个参数。从语法角度上讲,可变长参数由一个基础类型名字和<code>...</code>组成,如<code>Int...</code>。可变长参数被认为是一个包含了基础类型元素的数组。即<code>Int...</code>就是<code>Int[]</code>。关于使用可变长参数的例子,见章节“可变长参数”。</p>
<p>为了指定一个<code>in-out</code>参数,可以在参数类型前加<code>inout</code>前缀。但是你不可以对可变长参数或返回值类型使用<code>inout</code>。关于In-Out参数的讨论见章节In-Out参数部分。</p>
<p>柯里化函数curried function的类型相当于一个嵌套函数类型。例如下面的柯里化函数<code>addTwoNumber()()</code>的类型是<code>Int -&gt; Int -&gt; Int</code></p>
<pre><code class="lang-javascript">func addTwoNumbers(a: Int)(b: Int) -&gt; Int{
<span class="hljs-keyword">return</span> a + b
}
addTwoNumbers(<span class="hljs-number">4</span>)(<span class="hljs-number">5</span>) <span class="hljs-comment">// returns 9</span>
</code></pre>
<p>柯里化函数的函数类型从右向左组成一组。例如,函数类型<code>Int -&gt; Int -&gt; Int</code>可以被理解为<code>Int -&gt; (Int -&gt; Int)</code>——也就是说,一个函数传入一个<code>Int</code>然后输出作为另一个函数的输入,然后又返回一个<code>Int</code>。例如,你可以使用如下嵌套函数来重写柯里化函数<code>addTwoNumbers()()</code></p>
<pre><code class="lang-javascript">func addTwoNumbers(a: Int) -&gt; (Int -&gt; Int){
func addTheSecondNumber(b: Int) -&gt; Int{
<span class="hljs-keyword">return</span> a + b
}
<span class="hljs-keyword">return</span> addTheSecondNumber
}
addTwoNumbers(<span class="hljs-number">4</span>)(<span class="hljs-number">5</span>) <span class="hljs-comment">// Returns 9</span>
</code></pre>
<blockquote>
<p>函数类型的语法:
<em>function-type</em><em>type</em> <strong>-&gt;</strong> <em>type</em></p>
</blockquote>
<h2 id="-">数组类型</h2>
<p>Swift语言使用类型名紧接中括号<code>[]</code>来简化标准库中定义的命名型类型<code>Array&lt;T&gt;</code>。换句话说,下面两个声明是等价的:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> someArray: <span class="hljs-built_in">String</span>[] = [<span class="hljs-string">"Alex"</span>, <span class="hljs-string">"Brian"</span>, <span class="hljs-string">"Dave"</span>]
<span class="hljs-keyword">let</span> someArray: <span class="hljs-built_in">Array</span>&lt;<span class="hljs-built_in">String</span>&gt; = [<span class="hljs-string">"Alex"</span>, <span class="hljs-string">"Brian"</span>, <span class="hljs-string">"Dave"</span>]
</code></pre>
<p>上面两种情况下,常量<code>someArray</code>都被声明为字符串数组。数组的元素也可以通过<code>[]</code>获取访问:<code>someArray[0]</code>是指第0个元素<code>“Alex”</code></p>
<p>上面的例子同时显示,你可以使用<code>[]</code>作为初始值构造数组,空的<code>[]</code>则用来来构造指定类型的空数组。</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> emptyArray: Double[] = []
</code></pre>
<p>你也可以使用链接起来的多个<code>[]</code>集合来构造多维数组。例如,下例使用三个<code>[]</code>集合来构造三维整型数组:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> array3D: Int[][][] = [[[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>]], [[<span class="hljs-number">5</span>, <span class="hljs-number">6</span>], [<span class="hljs-number">7</span>, <span class="hljs-number">8</span>]]]
</code></pre>
<p>访问一个多维数组的元素时,最左边的下标指向最外层数组的相应位置元素。接下来往右的下标指向第一层嵌入的相应位置元素,依次类推。这就意味着,在上面的例子中,<code>array3D[0]</code>是指<code>[[1, 2], [3, 4]]</code><code>array3D[0][1]</code>是指<code>[3, 4]</code><code>array3D[0][1][1]</code>则是指值<code>4</code></p>
<p>关于Swift标准库中<code>Array</code>类型的细节讨论见章节Arrays。</p>
<blockquote>
<p>数组类型的语法:
<em>array-type</em><em>type</em><code>[ ]</code> | <em>array-type</em><code>[ ]</code></p>
</blockquote>
<h2 id="-">可选类型</h2>
<p>Swift定义后缀<code>?</code>来作为标准库中的定义的命名型类型<code>Optional&lt;T&gt;</code>的简写。换句话说,下面两个声明是等价的:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> optionalInteger: Int?
<span class="hljs-keyword">var</span> optionalInteger: Optional&lt;Int&gt;
</code></pre>
<p>在上述两种情况下,变量<code>optionalInteger</code>都被声明为可选整型类型。注意在类型和<code>?</code>之间没有空格。</p>
<p>类型<code>Optional&lt;T&gt;</code>是一个枚举,有两种形式,<code>None</code><code>Some(T)</code>,又来代表可能出现或可能不出现的值。任意类型都可以被显式的声明(或隐式的转换)为可选类型。当声明一个可选类型时,确保使用括号给<code>?</code>提供合适的作用范围。比如说,声明一个整型的可选数组,应写作<code>(Int[])?</code>,写成<code>Int[]?</code>的话则会出错。</p>
<p>如果你在声明或定义可选变量或特性的时候没有提供初始值,它的值则会自动赋成缺省值<code>nil</code></p>
<p>可选符合<code>LogicValue</code>协议,因此可以出现在布尔值环境下。此时,如果一个可选类型<code>T?</code>实例包含有类型为<code>T</code>的值(也就是说值为<code>Optional.Some(T)</code>),那么此可选类型就为<code>true</code>,否则为<code>false</code></p>
<p>如果一个可选类型的实例包含一个值,那么你就可以使用后缀操作符<code>!</code>来获取该值,正如下面描述的:</p>
<pre><code class="lang-javascript">optionalInteger = <span class="hljs-number">42</span>
optionalInteger! <span class="hljs-comment">// 42</span>
</code></pre>
<p>使用<code>!</code>操作符获取值为<code>nil</code>的可选项会导致运行错误runtime error</p>
<p>你也可以使用可选链和可选绑定来选择性的执行可选表达式上的操作。如果值为<code>nil</code>,不会执行任何操作因此也就没有运行错误产生。</p>
<p>更多细节以及更多如何使用可选类型的例子,见章节“可选”。</p>
<blockquote>
<p>可选类型语法:
<em>optional-type</em><em>type</em>?</p>
</blockquote>
<h2 id="-">隐式解析可选类型</h2>
<p>Swift语言定义后缀<code>!</code>作为标准库中命名类型<code>ImplicitlyUnwrappedOptional&lt;T&gt;</code>的简写。换句话说,下面两个声明等价:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> implicitlyUnwrappedString: <span class="hljs-built_in">String</span>!
<span class="hljs-keyword">var</span> implicitlyUnwrappedString: ImplicitlyUnwrappedOptional&lt;<span class="hljs-built_in">String</span>&gt;
</code></pre>
<p>上述两种情况下,变量<code>implicitlyUnwrappedString</code>被声明为一个隐式解析可选类型的字符串。注意类型与<code>!</code>之间没有空格。</p>
<p>你可以在使用可选的地方同样使用隐式解析可选。比如,你可以将隐式解析可选的值赋给变量、常量和可选特性,反之亦然。</p>
<p>有了可选,你在声明隐式解析可选变量或特性的时候就不用指定初始值,因为它有缺省值<code>nil</code></p>
<p>由于隐式解析可选的值会在使用时自动解析,所以没必要使用操作符<code>!</code>来解析它。也就是说,如果你使用值为<code>nil</code>的隐式解析可选,就会导致运行错误。</p>
<p>使用可选链会选择性的执行隐式解析可选表达式上的某一个操作。如果值为<code>nil</code>,就不会执行任何操作,因此也不会产生运行错误。</p>
<p>关于隐式解析可选的更多细节,见章节“隐式解析可选”。</p>
<blockquote>
<p>隐式解析可选的语法:
implicitly-unwrapped-optional-type → type!</p>
</blockquote>
<h2 id="-">协议合成类型</h2>
<p>协议合成类型是一种符合每个协议的指定协议列表类型。协议合成类型可能会用在类型标注和泛型参数中。</p>
<p>协议合成类型的形式如下:</p>
<pre><code class="lang-javascript">protocol&lt;Protocol <span class="hljs-number">1</span>, Procotol <span class="hljs-number">2</span>&gt;
</code></pre>
<p>协议合成类型允许你指定一个值,其类型可以适配多个协议的条件,而且不需要定义一个新的命名型协议来继承其它想要适配的各个协议。比如,协议合成类型<code>protocol&lt;Protocol A, Protocol B, Protocol C&gt;</code>等效于一个从<code>Protocol A</code><code>Protocol B</code> <code>Protocol C</code>继承而来的新协议<code>Protocol D</code>,很显然这样做有效率的多,甚至不需引入一个新名字。</p>
<p>协议合成列表中的每项必须是协议名或协议合成类型的类型别名。如果列表为空,它就会指定一个空协议合成列表,这样每个类型都能适配。</p>
<blockquote>
<p>协议合成类型的语法:
<em>protocol-composition-type</em><strong>protocol</strong> &lt;<em>protocol-identifier-list[opt]</em>&gt;
<em>protocol-identifier-list</em><em>protocol-identifier</em> | <em>protocol-identifier, protocol-identifier-list</em>
<em>protocol-identifier</em><em>type-identifier</em></p>
</blockquote>
<h2 id="-">元类型</h2>
<p>元类型是指所有类型的类型,包括类、结构体、枚举和协议。</p>
<p>类、结构体或枚举类型的元类型是相应的类型名紧跟<code>.Type</code>。协议类型的元类型——并不是运行时适配该协议的具体类型——是该协议名字紧跟<code>.Protocol</code>。比如,类<code>SomeClass</code>的元类型就是<code>SomeClass.Type</code>,协议<code>SomeProtocol</code>的元类型就是<code>SomeProtocal.Protocol</code></p>
<p>你可以使用后缀<code>self</code>表达式来获取类型。比如,<code>SomeClass.self</code>返回<code>SomeClass</code>本身,而不是<code>SomeClass</code>的一个实例。同样,<code>SomeProtocol.self</code>返回<code>SomeProtocol</code>本身,而不是运行时适配<code>SomeProtocol</code>的某个类型的实例。还可以对类型的实例使用<code>dynamicType</code>表达式来获取该实例在运行阶段的类型,如下所示:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">class</span> SomeBaseClass {
<span class="hljs-keyword">class</span> func printClassName() {
println(<span class="hljs-string">"SomeBaseClass"</span>)
}
}
<span class="hljs-keyword">class</span> SomeSubClass: SomeBaseClass {
override <span class="hljs-keyword">class</span> func printClassName() {
println(<span class="hljs-string">"SomeSubClass"</span>)
}
}
<span class="hljs-keyword">let</span> someInstance: SomeBaseClass = SomeSubClass()
<span class="hljs-comment">// someInstance is of type SomeBaseClass at compile time, but</span>
<span class="hljs-comment">// someInstance is of type SomeSubClass at runtime</span>
someInstance.dynamicType.printClassName()
<span class="hljs-comment">// prints "SomeSubClass</span>
</code></pre>
<blockquote>
<p>元类型的语法:
<em>metatype-type</em><em>type</em>.<strong>Type</strong> | <em>type</em>.<strong>Protocol</strong></p>
</blockquote>
<h2 id="-">类型继承子句</h2>
<p>类型继承子句被用来指定一个命名型类型继承哪个类且适配哪些协议。类型继承子句开始于冒号<code>:</code>,紧跟由<code>,</code>隔开的类型标识符列表。</p>
<p>类可以继承单个超类,适配任意数量的协议。当定义一个类时,超类的名字必须出现在类型标识符列表首位,然后跟上该类需要适配的任意数量的协议。如果一个类不是从其它类继承而来,那么列表可以以协议开头。关于类继承更多的讨论和例子,见章节“继承”。</p>
<p>其它命名型类型可能只继承或适配一个协议列表。协议类型可能继承于其它任意数量的协议。当一个协议类型继承于其它协议时,其它协议的条件集合会被集成在一起,然后其它从当前协议继承的任意类型必须适配所有这些条件。</p>
<p>枚举定义中的类型继承子句可以是一个协议列表,或是指定原始值的枚举,一个单独的指定原始值类型的命名型类型。使用类型继承子句来指定原始值类型的枚举定义的例子,见章节“原始值”。</p>
<blockquote>
<p>类型继承子句的语法:
<em>type-inheritance-clause</em> → :<em>type-inheritance-list</em>
<em>type-inheritance-list</em><em>type-identifier</em> | <em>type-identifier</em>, <em>type-inheritance-list</em></p>
</blockquote>
<h2 id="-">类型推断</h2>
<p>Swift广泛的使用类型推断从而允许你可以忽略很多变量和表达式的类型或部分类型。比如对于<code>var x: Int = 0</code>,你可以完全忽略类型而简写成<code>var x = 0</code>——编译器会正确的推断出<code>x</code>的类型<code>Int</code>。类似的,当完整的类型可以从上下文推断出来时,你也可以忽略类型的一部分。比如,如果你写了<code>let dict: Dictionary = [&quot;A&quot;: 1]</code>,编译提也能推断出<code>dict</code>的类型是<code>Dictionary&lt;String, Int&gt;</code></p>
<p>在上面的两个例子中类型信息从表达式树expression tree的叶子节点传向根节点。也就是说<code>var x: Int = 0</code><code>x</code>的类型首先根据<code>0</code>的类型进行推断,然后将该类型信息传递到根节点(变量<code>x</code>)。</p>
<p>在Swift中类型信息也可以反方向流动——从根节点传向叶子节点。在下面的例子中常量<code>eFloat</code>上的显式类型标注(<code>:Float</code>)导致数字字面量<code>2.71828</code>的类型是<code>Float</code>而非<code>Double</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> e = <span class="hljs-number">2.71828</span> <span class="hljs-comment">// The type of e is inferred to be Double.</span>
<span class="hljs-keyword">let</span> eFloat: Float = <span class="hljs-number">2.71828</span> <span class="hljs-comment">// The type of eFloat is Float.</span>
</code></pre>
<p>Swift中的类型推断在单独的表达式或语句水平上进行。这意味着所有用于推断类型的信息必须可以从表达式或其某个子表达式的类型检查中获取。</p>
</section>
</div>
</div>
</div>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="3.4" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="3.4" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="3.6" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="3.6" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="3.7" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="3.7" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_45">
<section class="normal" id="section-gitbook_50">
<h1 id="-">特性</h1>
<p>特性提供了关于声明和类型的更多信息。在Swift中有两类特性用于修饰声明的以及用于修饰类型的。例如<code>required</code>特性,当应用于一个类的指定或便利初始化器声明时,表明它的每个子类都必须实现那个初始化器。再比如<code>noreturn</code>特性,当应用于函数或方法类型时,表明该函数或方法不会返回到它的调用者。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="3.8" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="3.8" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="3.9" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="3.9" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,6 +587,78 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_58">
<h1 id="-">泛型参数</h1>
<hr>
<p>本页包含内容:</p>
<ul>
<li><a href="#label1">泛型形参语句</a></li>
<li><a href="#label2">泛型实参语句</a></li>
</ul>
<p>本节涉及泛型类型、泛型函数以及泛型构造器的参数,包括形参和实参。声明泛型类型、函数或构造器时,须指定相应的类型参数。类型参数相当于一个占位符,当实例化泛型类型、调用泛型函数或泛型构造器时,就用具体的类型实参替代之。</p>
<p>关于 Swift 语言的泛型概述,见<a href="../charpter2/22_Generics.html">泛型</a>(第二部分第22章)。</p>
<h2 id="-a-name-label1-a-"><a name="label1">泛型实参语句</a></h2>
<p>泛型形参语句指定泛型类型或函数的类型形参,以及这些参数的关联约束和要求。泛型形参语句用尖括号(&lt;&gt;)包住,并且有以下两种声明形式:</p>
<pre><code>&lt;generic parameter list&gt;
&lt;generic parameter list where requirements &gt;
</code></pre><p>泛型形参列表中泛型形参用逗号分开,每一个采用以下形式:</p>
<pre><code>type parameter : constrain
</code></pre><p>泛型形参由两部分组成类型形参及其后的可选约束。类型形参只是占位符类型如TUVKeyTypeValueType等的名字而已。你可以在泛型类型、函数的其余部分或者构造器声明以及函数或构造器的签名中使用它。</p>
<p>约束用于指明该类型形参继承自某个类或者遵守某个协议或协议的一部分。例如,在下面的泛型中,泛型形参<code>T: Comparable</code>表示任何用于替代类型形参<code>T</code>的类型实参必须满足<code>Comparable</code>协议。</p>
<pre><code>func simpleMin&lt;T: COmparable&gt;(x: T, y: T) -&gt; T {
if x &lt; y {
return y
}
return x
}
</code></pre><p>如,<code>Int</code><code>Double</code>均满足<code>Comparable</code>协议,该函数接受任何一种类型。与泛型类型相反,调用泛型函数或构造器时不需要指定泛型实参语句。类型实参由传递给函数或构造器的实参推断而出。</p>
<pre><code>simpleMin(17, 42) // T is inferred to be Int
simpleMin(3.14159, 2.71828) // T is inferred to be Double
</code></pre><h2 id="where-">Where语句</h2>
<p>要想对类型形参及其关联类型指定额外要求,可以在泛型形参列表之后添加<code>where</code>语句。<code>where</code>语句由关键字<code>where</code>及其后的用逗号分割的多个要求组成。</p>
<p><code>where</code>语句中的要求用于指明该类型形参继承自某个类或遵守某个协议或协议的一部分。尽管<code>where</code>语句有助于表达类型形参上的简单约束(如<code>T: Comparable</code>等同于<code>T where T: Comparable</code>,等等),但是依然可以用来对类型形参及其关联约束提供更复杂的约束。如,<code>&lt;T where T: C, T: P&gt;</code>表示泛型类型<code>T</code>继承自类<code>C</code>且遵守协议<code>P</code></p>
<p>如上所述,可以强制约束类型形参的关联类型遵守某个协议。<code>&lt;T: Generator where T.Element: Equatable&gt;</code>表示<code>T</code>遵守<code>Generator</code>协议,而且<code>T</code>的关联类型<code>T.Element</code>遵守<code>Eauatable</code>协议(<code>T</code>有关联类型是因为<code>Generator</code>声明了<code>Element</code>,而<code>T</code>遵守<code>Generator</code>协议)。</p>
<p>也可以用操作符<code>==</code>来指定两个类型等效的要求。例如,有这样一个约束:<code>T</code><code>U</code>遵守<code>Generator</code>协议,同时要求它们的关联类型等同,可以这样来表达:<code>&lt;T: Generator, U: Generator where T.Element == U.Element&gt;</code></p>
<p>当然,替代类型形参的类型实参必须满足所有类型形参所要求的约束和要求。</p>
<p>泛型函数或构造器可以重载,但在泛型形参语句中的类型形参必须有不同的约束或要求,抑或二者皆不同。当调用重载的泛型函数或构造器时,编译器会用这些约束来决定调用哪个重载函数或构造器。</p>
<p>泛型类可以生成一个子类,但是这个子类也必须是泛型类。</p>
<blockquote>
<p>Grammar of a generic parameter clause</p>
<p>parameter-clause → &lt;­generic-parameter-list­requirement-clause &gt;</p>
<p>­generic-parameter-list → generic-parameter­ generic-parameter­,­generic-parameter-list ­</p>
<p>generic-parameter → type-name­</p>
<p>generic-parameter → type-name­:­type-identifier­</p>
<p>generic-parameter → type-name­:­protocol-composition-type­</p>
<p>requirement-clause → <code>where</code>­requirement-list­</p>
<p>requirement-list → requirement­ requirement­,­requirement-list­</p>
<p>requirement → conformance-requirement­ same-type-requirement­</p>
<p>conformance-requirement → type-identifier­:­type-identifier­</p>
<p>conformance-requirement → type-identifier­:­protocol-composition-type­</p>
<p>same-type-requirement → type-identifier­==­type-identifier</p>
</blockquote>
<h2 id="-a-name-label2-a-"><a name="label2">泛型实参语句</a></h2>
<p>泛型实参语句指定泛型类型的类型实参。泛型实参语句用尖括号(&lt;&gt;)包住,并且按如下形式声明:</p>
<pre><code>&lt; generic argument list &gt;
</code></pre><p>泛型实参列表中类型实参有逗号分开。类型实参是实际具体类型的名字用来替代泛型类型的泛型形参语句中的相应的类型形参。从而得到泛型类型的一个特化版本。如Swift标准库的泛型字典类型定义如下</p>
<pre><code> struct Dictionary&lt;KeyTypel: Hashable, ValueType&gt;: Collection,
DictionaryLiteralConvertible {
/* .. */
}
</code></pre><p>泛型<code>Dictionary</code>类型的特化版本,<code>Dictionary&lt;String, Int&gt;</code>就是用具体的<code>String</code><code>Int</code>类型替代泛型类型<code>KeyType: Hashable</code><code>ValueType</code>产生的。每一个类型实参必须满足它所替代的泛型形参的所有约束,包括任何<code>where</code>语句所指定的额外的要求。上面的例子中,类型形参<code>KeyType</code>要求满足<code>Hashable</code>协议,因此<code>String</code>也必须满足<code>Hashable</code>协议。</p>
<p>可以用本身就是泛型类型的特化版本的类型实参替代类型形参(假设已满足合适的约束和要求)。例如,为了生成一个元素类型是整型数组的数组,可以用数组的特化版本<code>Array&lt;Int&gt;</code>替代泛型类型<code>Array&lt;T&gt;</code>的类型形参<code>T</code>来实现。</p>
<pre><code>let arrayOfArrays: Array&lt;Array&lt;Int&gt;&gt; = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
</code></pre><p><a href="#label1">泛型形参语句</a>一样,不能用泛型实参语句来指定泛型函数或构造器的类型实参。</p>
<blockquote>
<p>Grammar of a generic argument clause</p>
<p>generic-argument-clause → &lt;­generic-argument-list­&gt;­</p>
<p>generic-argument-list → generic-argument­ generic-argument­,­generic-argument-list­</p>
<p>generic-argument → type</p>
</blockquote>
</section>
</div>
</div>
</div>

View File

@ -44,7 +44,7 @@
<div class="book" data-level="3.10" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="3.10" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="3.5" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="3.5" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -587,7 +587,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_54">
<section class="normal" id="section-gitbook_61">
<h1 id="-">语句</h1>
<p>在 Swift 中有两种类型的语句简单语句和控制流语句。简单语句是最常见的用于构造表达式和声明。控制流语句则用于控制程序执行的流程Swift 中有三种类型的控制流语句:循环语句、分支语句和控制传递语句。</p>

View File

@ -46,7 +46,7 @@
<div class="book" data-level="3" data-basepath=".." data-revision="1402305571512">
<div class="book" data-level="3" data-basepath=".." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>

View File

@ -44,7 +44,7 @@
<div class="book" data-level="0" data-basepath="." data-revision="1402305571512">
<div class="book" data-level="0" data-basepath="." data-revision="1402328527093">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -585,7 +585,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_3">
<section class="normal" id="section-gitbook_8">
<h1 id="swift-">Swift 编程语言</h1>
<p>Swift 是苹果在 WWDC 2014 上发布的一款全新的编程语言,本书译自苹果官方的 Swift 教程《The Swift Programming Language》。</p>

View File

@ -1,5 +1,5 @@
CACHE MANIFEST
# Revision 1402305571513
# Revision 1402328527096
CACHE:
index.html

File diff suppressed because one or more lines are too long

View File

@ -245,7 +245,7 @@
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)
函数实际上是一种特殊的闭包你可以使用`{}`来创建一个匿名闭包使用`in`来分割参数并返回类型
函数实际上是一种特殊的闭包你可以使用`{}`来创建一个匿名闭包使用`in`来分割参数返回值与执行体
numbers.map({
(number: Int) -> Int in

View File

@ -199,7 +199,7 @@ let c = a++ // a 现在 2, 但 c 是 a 自增前的值 1
```swift
let three = 3
let minusThree = -three // minusThree 等于 -3
let plusThree = -minusThree // plusThree 等于 3, o或 "负负3"
let plusThree = -minusThree // plusThree 等于 3, 或 "负负3"
```
单目负号写在操作数之前, 中间没有空格.

View File

@ -254,9 +254,8 @@ Swift统一的函数语法足够灵活可以用来表示任何函数包括
在这个例子中Swift自动为`joiner`提供了外部参数名。因此,当函数调用时,外部参数名必须使用,这样使得参数的用途变得清晰。
func join(s1: String, s2: String, joiner: String = " ") -> String {
return s1 + joiner + s2
}
join("hello", "world", joiner: "-")
// returns "hello-world"
> 注意:
> 你可以使用`下划线_`作为默认值参数的外部参数名,这样可以在调用时不用提供外部参数名。但是给带默认值的参数命名总是更加合适的。
@ -319,7 +318,7 @@ Swift统一的函数语法足够灵活可以用来表示任何函数包括
变量参数正如上面所述仅仅能在函数体内被更改。如果你想要一个函数可以修改参数的值并且想要在这些修改在函数调用结束后仍然存在那么就应该把这个参数定义为输入输出参数In-Out Parameters
定义一个输入输出参数时,在参数定前加`inout`关键字。一个输入输出参数有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值。
定义一个输入输出参数时,在参数定前加`inout`关键字。一个输入输出参数有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值。
你只能传入一个变量作为输入输出参数。你不能传入常量或者字面量literal value因为这些量是不能被修改的。当传入的参数作为输入输出参数时需要在参数前加`&`符,表示这个值可以被函数修改。

View File

@ -4,16 +4,16 @@
- 枚举语法
- 匹配枚举值与`Swith`语句
- 实例associated values
- 关联associated values
- 原始值raw values
枚举enumeration定义了一个通用类型的一组相关的值使你可以在你的代码中以一个安全的方式来使用这些值。
如果你熟悉C语言你就会知道在C语言中枚举指定相关名称为一组整型值。Swift中的枚举更加灵活不必给每一个枚举成员enumeration member提供一个值。如果一个值被认为是“原始”值被提供给每个枚举成员则该值可以是一个字符串一个字符或是一个整型值或浮点值。
此外,枚举成员可以指定任何类型的实例值存储到枚举成员值中就像其他语言中的联合体unions和变体variants。你可以定义一组通用的相关成员作为枚举的一部分每一组都有不同的一组与它相关的适当类型的数值。
此外,枚举成员可以指定任何类型的关联值存储到枚举成员值中就像其他语言中的联合体unions和变体variants。你可以定义一组通用的相关成员作为枚举的一部分每一组都有不同的一组与它相关的适当类型的数值。
在Swift中枚举类型是一等first-class类型。它们采用了很多传统上只被类class)所支持的特征例如计算型属性computed properties),用于提供关于枚举当前值的附加信息, 实例方法instance methods用于提供和枚举所代表的值相关联的功能。枚举也可以定义构造函数initializers来提供一个初始成员值可以在原始的实现基础上扩展它们的功能可以遵守协议protocols来提供标准的功能。
在Swift中枚举类型是一等first-class类型。它们采用了很多传统上只被类class)所支持的特征例如计算型属性computed properties)用于提供关于枚举当前值的附加信息实例方法instance methods用于提供和枚举所代表的值相关联的功能。枚举也可以定义构造函数initializers来提供一个初始成员值可以在原始的实现基础上扩展它们的功能可以遵守协议protocols来提供标准的功能。
欲了解更多相关功能请参见属性Properties方法Methods构造过程Initialization扩展Extensions和协议Protocols
@ -91,11 +91,11 @@
}
// prints "Mostly harmless”
## 实例Associated Values
## 关联Associated Values
上一小节的例子演示了一个枚举的成员是如何被定义(分类)的。你可以为`Planet.Earth`设置一个常量或则变量,并且在之后查看这个值。然而,有时候会很有用如果能够把其他类型的实例值和成员值一起存储起来。这能让你随着成员值存储额外的自定义信息,并且当每次你在代码中利用该成员时允许这个信息产生变化。
上一小节的例子演示了一个枚举的成员是如何被定义(分类)的。你可以为`Planet.Earth`设置一个常量或则变量,并且在之后查看这个值。然而,有时候会很有用如果能够把其他类型的关联值和成员值一起存储起来。这能让你随着成员值存储额外的自定义信息,并且当每次你在代码中利用该成员时允许这个信息产生变化。
你可以定义Swift的枚举存储任何类型的实例如果需要的话每个成员的数据类型可以是各不相同的。枚举的这种特性跟其他语言中的可辨识联合discriminated unions标签联合tagged unions或者变体variants相似。
你可以定义Swift的枚举存储任何类型的关联如果需要的话每个成员的数据类型可以是各不相同的。枚举的这种特性跟其他语言中的可辨识联合discriminated unions标签联合tagged unions或者变体variants相似。
例如假设一个库存跟踪系统需要利用两种不同类型的条形码来跟踪商品。有些商品上标有UPC-A格式的一维码它使用数字0到9.每一个条形码都有一个代表“数字系统”的数字该数字后接10个代表“标识符”的数字。最后一个数字是“检查”位用来验证代码是否被正确扫描
@ -116,23 +116,23 @@
以上代码可以这么理解:
“定义一个名为`Barcode`的枚举类型,它可以是`UPCA`的一个实例值(`Int``Int``Int`),或者`QRCode`的一个字符串类型(`String`实例值。”
“定义一个名为`Barcode`的枚举类型,它可以是`UPCA`的一个关联值(`Int``Int``Int`),或者`QRCode`的一个字符串类型(`String`关联值。”
这个定义不提供任何`Int``String`的实际值,它只是定义了,当`Barcode`常量和变量等于`Barcode.UPCA``Barcode.QRCode`时,实例值的类型。
这个定义不提供任何`Int``String`的实际值,它只是定义了,当`Barcode`常量和变量等于`Barcode.UPCA``Barcode.QRCode`时,关联值的类型。
然后可以使用任何一种条码类型创建新的条码,如:
var productBarcode = Barcode.UPCA(8, 85909_51226, 3)
以上例子创建了一个名为`productBarcode`的新变量,并且赋给它一个`Barcode.UPCA`实例元组值`(8, 8590951226, 3)`。提供的“标识符”值在整数字中有一个下划线,使其便于阅读条形码。
以上例子创建了一个名为`productBarcode`的新变量,并且赋给它一个`Barcode.UPCA`关联元组值`(8, 8590951226, 3)`。提供的“标识符”值在整数字中有一个下划线,使其便于阅读条形码。
同一个商品可以被分配给一个不同类型的条形码,如:
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
这时,原始的`Barcode.UPCA`和其整数值被新的`Barcode.QRCode`和其字符串值所替代。条形码的常量和变量可以存储一个`.UPCA`或者一个`.QRCode`(连同它的实例值),但是在任何指定时间只能存储其中之一。
这时,原始的`Barcode.UPCA`和其整数值被新的`Barcode.QRCode`和其字符串值所替代。条形码的常量和变量可以存储一个`.UPCA`或者一个`.QRCode`(连同它的关联值),但是在任何指定时间只能存储其中之一。
像以前那样不同的条形码类型可以使用一个switch语句来检查然而这次实例值可以被提取作为switch语句的一部分。你可以在`switch`的case分支代码中提取每个实例值作为一个常量(用`let`前缀)或者作为一个变量(用`var`前缀)来使用:
像以前那样不同的条形码类型可以使用一个switch语句来检查然而这次关联值可以被提取作为switch语句的一部分。你可以在`switch`的case分支代码中提取每个关联值作为一个常量(用`let`前缀)或者作为一个变量(用`var`前缀)来使用:
switch productBarcode {
case .UPCA(let numberSystem, let identifier, let check):
@ -142,7 +142,7 @@
}
// prints "QR code with value of ABCDEFGHIJKLMNOP.”
如果一个枚举成员的所有实例值被提取为常量,或者它们全部被提取为变量,为了简洁,你可以只放置一个`var`或者`let`标注在成员名称前:
如果一个枚举成员的所有关联值被提取为常量,或者它们全部被提取为变量,为了简洁,你可以只放置一个`var`或者`let`标注在成员名称前:
switch productBarcode {
case let .UPCA(numberSystem, identifier, check):
@ -154,7 +154,7 @@
## 原始值Raw Values
实例值小节的条形码例子中演示了一个枚举的成员如何声明它们存储不同类型的实例值。作为实例值的替代,枚举成员可以被默认值(称为原始值)预先填充,其中这些原始值具有相同的类型。
关联值小节的条形码例子中演示了一个枚举的成员如何声明它们存储不同类型的关联值。作为关联值的替代,枚举成员可以被默认值(称为原始值)预先填充,其中这些原始值具有相同的类型。
这里是一个枚举成员存储原始ASCII值的例子
@ -166,7 +166,7 @@
在这里,称为`ASCIIControlCharacter`的枚举的原始值类型被定义为字符型`Character`并被设置了一些比较常见的ASCII控制字符。字符值的描述请详见字符串和字符`Strings and Characters`部分。
注意,原始值和实例值是不相同的。当你开始在你的代码中定义枚举的时候原始值是被预先填充的值像上述三个ASCII码。对于一个特定的枚举成员它的原始值始终是相同的。实例值是当你在创建一个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做得时候,它的值可以是不同的。
注意,原始值和关联值是不相同的。当你开始在你的代码中定义枚举的时候原始值是被预先填充的值像上述三个ASCII码。对于一个特定的枚举成员它的原始值始终是相同的。关联值是当你在创建一个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做得时候,它的值可以是不同的。
原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。当整型值被用于原始值,如果其他枚举成员没有值时,它们会自动递增。

View File

@ -0,0 +1,295 @@
# 语法结构
本页包含内容:
- 空白与注释(*Whitespace and Comments*
- 标识符(*Identifiers*
- 关键字(*Keywords*
- 字面量(*Literals*
- 运算符(*Operators*
Swift 的“语法结构(*lexical structure*)”描述了如何在该语言中用字符序列构建合法标记,组成该语言中最底层的代码块,并在之后的章节中用于描述语言的其他部分。
通常,标记在随后介绍的语法约束下,由 Swift 源文件的输入文本中提取可能的最长子串生成。这种方法称为“最长匹配项(*longest match*)”,或者“最大适合”(*maximal munch*)。
## 空白与注释
空白(*whitespace*)有两个用途:分隔源文件中的标记和区分运算符属于前缀还是后缀,(参见 [运算符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-XID_871))在其他情况下则会被忽略。以下的字符会被当作空白:空格(*space*U+0020、换行符*line feed*U+000A、回车符*carriage return*U+000D、水平 tab*horizontal tab*U+0009、垂直 tab*vertical tab*U+000B、换页符*form feed*U+000C以及空*null*U+0000
注释(*comments*)被编译器当作空白处理。单行注释由 `//` 开始直到该行结束。多行注释由 `/*` 开始,以 `*/` 结束。可以嵌套注释,但注意注释标记必须匹配。
## 标识符
标识符(*identifiers*)可以由以下的字符开始:大写或小写的字母 `A``Z`、下划线 `_`、基本多语言面(*Basic Multilingual Plane*)中的 Unicode 非组合字符以及基本多语言面以外的非专用区(*Private Use Area*)字符。首字符之后,标识符允许使用数字和 Unicode 字符组合。
使用保留字(*reserved word*)作为标识符,需要在其前后增加反引号 <code>\`</code>。例如,<code>class</code> 不是合法的标识符,但可以使用 <code>\`class\`</code>。反引号不属于标识符的一部分,<code>\`x\`</code>`x` 表示同一标识符。
闭包(*closure*)中如果没有明确指定参数名称,参数将被隐式命名为 <code>$0</code><code>$1</code><code>$2</code>... 这些命名在闭包作用域内是合法的标识符。
> 标识符语法
>
> *identifier* → [identifier-head­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-head) [identifier-characters](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-characters)­ *opt*
>
> *identifier* → \`­ [identifier-head­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-head) [identifier-characters­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-characters) *opt­* \`­
>
> *identifier* → [implicit-parameter-name­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/implicit-parameter-name)
>
> *identifier-list* → [identifier­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier) | [identifier­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier) , [­identifier-list](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-list)­
>
> *identifier-head* → A 到 Z 大写或小写字母
>
> *identifier-head* → U+00A8, U+00AA, U+00AD, U+00AF, U+00B2U+00B5, 或 U+00B7U+00BA
>
> *identifier-head* → U+00BCU+00BE, U+00C0U+00D6, U+00D8U+00F6, 或 U+00F8U+00FF
>
> *identifier-head* → U+0100U+02FF, U+0370U+167F, U+1681U+180D, 或 U+180FU+1DBF
>
> *identifier-head* → U+1E00U+1FFF
>
> *identifier-head* → U+200BU+200D, U+202AU+202E, U+203FU+2040, U+2054, 或 U+2060U+206F
>
> *identifier-head* → U+2070U+20CF, U+2100U+218F, U+2460U+24FF, 或 U+2776U+2793
>
> *identifier-head* → U+2C00U+2DFF 或 U+2E80U+2FFF
>
> *identifier-head* → U+3004U+3007, U+3021U+302F, U+3031U+303F, 或 U+3040U+D7FF
>
> *identifier-head* → U+F900U+FD3D, U+FD40U+FDCF, U+FDF0U+FE1F, 或 U+FE30U+FE44
>
> *identifier-head* → U+FE47U+FFFD
>
> *identifier-head* → U+10000U+1FFFD, U+20000U+2FFFD, U+30000U+3FFFD, 或 U+40000U+4FFFD
>
> *identifier-head* → U+50000U+5FFFD, U+60000U+6FFFD, U+70000U+7FFFD, 或 U+80000U+8FFFD
>
> *identifier-head* → U+90000U+9FFFD, U+A0000U+AFFFD, U+B0000U+BFFFD, 或 U+C0000U+CFFFD
>
> *identifier-head* → U+D0000U+DFFFD 或 U+E0000U+EFFFD
>
> *identifier-character* → 数字 0 到 9
>
> *identifier-character* → U+0300U+036F, U+1DC0U+1DFF, U+20D0U+20FF, or U+FE20U+FE2F
>
> *identifier-character* → [identifier-head­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-head)
>
> *identifier-characters* → [identifier-character](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-character) [­identifier-characters­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/identifier-characters) *opt­*
>
> *implicit-parameter-name* → **$­** [decimal-digits­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-digits)
## 关键字
被保留的关键字(*keywords*)不允许用作标识符,除非被反引号转义,参见 [标识符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-XID_796)。
* **用作声明的关键字:** *class*、*deinit*、*enum*、*extension*、*func*、*import*、*init*、*let*、*protocol*、*static*、*struct*、*subscript*、*typealias*、*var*
* **用作语句的关键字:** *break*、*case*、*continue*、*default*、*do*、*else*、*fallthrough*、*if*、*in*、*for*、*return*、*switch*、*where*、*while*
* **用作表达和类型的关键字:** *as*、*dynamicType*、*is*、*new*、*super*、*self*、*Self*、*Type*、*\_\_COLUMN\_\_*、*\_\_FILE\_\_*、*\_\_FUNCTION\_\_*、*\_\_LINE\_\_*
* **特定上下文中被保留的关键字:** *associativity*、*didSet*、*get*、*infix*、*inout*、*left*、*mutating*、*none*、*nonmutating*、*operator*、*override*、*postfix*、*precedence*、*prefix*、*right*、*set*、*unowned*、*unowned(safe)*、*unowned(unsafe)*、*weak*、*willSet*,这些关键字在特定上下文之外可以被用于标识符。
## 字面量
字面值表示整型、浮点型数字或文本类型的值,举例如下:
42 // 整型字面量
3.14159 // 浮点型字面量
"Hello, world!" // 文本型字面量
> 字面量语法
>
> *literal* → [integer-literal­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/integer-literal) | [floating-point-literal](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/floating-point-literal)­ | [string-literal­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/string-literal)
### 整型字面量
整型字面量(*integer literals*)表示未指定精度整型数的值。整型字面量默认用十进制表示,可以加前缀来指定其他的进制,二进制字面量加 `0b`,八进制字面量加 `0o`,十六进制字面量加 `0x`
十进制字面量包含数字 `0``9`。二进制字面量只包含 `0``1`,八进制字面量包含数字 `0``7`,十六进制字面量包含数字 `0``9` 以及字母 `A``F` (大小写均可)。
负整数的字面量在数字前加减号 `-`,比如 `-42`
允许使用下划线 `_` 来增加数字的可读性,下划线不会影响字面量的值。整型字面量也可以在数字前加 `0`,同样不会影响字面量的值。
1000_000 // 等于 1000000
005 // 等于 5
除非特殊指定,整型字面量的默认类型为 Swift 标准库类型中的 `Int`。Swift 标准库还定义了其他不同长度以及是否带符号的整数类型,请参考 [整数类型](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_411)。
> 整型字面量语法
>
> *integer-literal* → [binary-literal­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/binary-literal)
>
> *integer-literal* → [octal-literal­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-literal)
>
> *integer-literal* → [decimal-literal­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal)
>
> *integer-literal* → [hexadecimal-literal](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal)­
>
> *binary-literal* → **0b**­ [binary-digit](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/binary-digit) ­[binary-literal-characters­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/binary-literal-characters) *opt­*
>
> *binary-digit* → 数字 0 或 1
>
> *binary-literal-character* → [binary-digit](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/binary-digit)­ | _­
>
> *binary-literal-characters* → [binary-literal-character](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/binary-literal-character) ­[binary-literal-characters­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/binary-literal-characters) *opt­*
>
> *octal-literal* → **0o**­ [octal-digit](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-digit) ­[octal-literal-characters­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-literal-characters) *opt­*
>
> *octal-digit* → 数字 0 至 7
>
> *octal-literal-character* → [octal-digit](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-digit)­ | _­
>
> *octal-literal-characters* → [octal-literal-character](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-literal-character) [­octal-literal-characters­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-literal-characters) *opt­*
>
> *decimal-literal* → [decimal-digit](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-digit) [­decimal-literal-characters­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal-characters) *opt­*
>
> *decimal-digit* → 数字 0 至 9
>
> *decimal-digits* → [decimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-digit) [decimal-digits­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-digits) *opt­*
>
> *decimal-literal-character* → [decimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-digit) | _­
>
> *decimal-literal-characters* → [decimal-literal-character](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal-character) ­[decimal-literal-characters­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal-characters) *opt­*
>
> *hexadecimal-literal* → **0x** ­[hexadecimal-digit](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit) [­hexadecimal-literal-characters­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal-characters) *opt­*
>
> *hexadecimal-digit* → 数字 0 到 9, a 到 f, 或 A 到 F
>
> *hexadecimal-literal-character* → [hexadecimal-digit](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit)­ | _­
>
> *hexadecimal-literal-characters* → [hexadecimal-literal-character­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal-character) [hexadecimal-literal-characters](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal-characters) ­*opt­*
### 浮点型字面量
浮点型字面量(*floating-point literals*)表示未指定精度浮点数的值。
浮点型字面量默认用十进制表示(无前缀),也可以用十六进制表示(加前缀 `0x`)。
十进制浮点型字面量(*decimal floating-point literals*)由十进制数字串后跟小数部分或指数部分(或两者皆有)组成。十进制小数部分由小数点 `.` 后跟十进制数字串组成。指数部分由大写或小写字母 `e` 后跟十进制数字串组成,这串数字表示 `e` 之前的数量乘以 10 的几次方。例如:`1.25e2` 表示 `1.25 ⨉ 10^2`,也就是 `125.0`;同样,`1.25e2` 表示 `1.25 ⨉ 10^2`,也就是 `0.0125`
十六进制浮点型字面量(*hexadecimal floating-point literals*)由前缀 `0x` 后跟可选的十六进制小数部分以及十六进制指数部分组成。十六进制小数部分由小数点后跟十六进制数字串组成。指数部分由大写或小写字母 `p` 后跟十进制数字串组成,这串数字表示 `p` 之前的数量乘以 2 的几次方。例如:`0xFp2` 表示 `15 ⨉ 2^2`,也就是 `60`;同样,`0xFp-2` 表示 `15 ⨉ 2^-2`,也就是 `3.75`
与整型字面量不同,负的浮点型字面量由一元运算符减号 `-` 和浮点型字面量组成,例如 `-42.0`。这代表一个表达式,而不是一个浮点整型字面量。
允许使用下划线 `_` 来增强可读性,下划线不会影响字面量的值。浮点型字面量也可以在数字前加 `0`,同样不会影响字面量的值。
10_000.56 // 等于 10000.56
005000.76 // 等于 5000.76
除非特殊指定,浮点型字面量的默认类型为 Swift 标准库类型中的 `Double`表示64位浮点数。Swift 标准库也定义 `Float` 类型表示32位浮点数。
> 浮点型字面量语法
>
> *floating-point-literal* → [decimal-literal](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal) ­[decimal-fraction­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-fraction) *opt* ­[decimal-exponent­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-exponent) *opt­*
>
> *floating-point-literal* → [hexadecimal-literal](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal) ­[hexadecimal-fraction](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-fraction) ­*opt­* [hexadecimal-exponent](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-exponent)­
>
> *decimal-fraction* → . [­decimal-literal­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal)
>
> *decimal-exponent* → [floating-point-e](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/floating-point-e) [­sign­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/sign) *opt­* [decimal-literal](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/decimal-literal)­
>
> *hexadecimal-fraction* → . [­hexadecimal-literal­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal) *opt­*
>
> *hexadecimal-exponent* → [floating-point-p­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/floating-point-p) [sign­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/sign) *opt­* [hexadecimal-literal­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-literal)
>
> *floating-point-e* → **e­** | **E**­
>
> *floating-point-p* → **p**­ | **P**­
>
> *sign* → **+**­ | **-**­
### 文本型字面量
文本型字面量(*string literal*)由双引号中的字符串组成,形式如下:
"characters"
文本型字面量中不能包含未转义的双引号 `"`、未转义的反斜线`\`、回车符(*carriage return*)或换行符(*line feed*)。
可以在文本型字面量中使用的转义特殊符号如下:
* 空字符Null Character`\0`
* 反斜线Backslash`\\`
* 水平 Tab Horizontal Tab`\t`
* 换行符Line Feed`\n`
* 回车符Carriage Return`\r`
* 双引号Double Quote`\"`
* 单引号Single Quote`\'`
字符也可以用以下方式表示:
* `\x` 后跟两位十六进制数字
* `\u` 后跟四位十六进制数字
* `\U` 后跟八位十六进制数字
后跟的数字表示一个 Unicode 码点。
文本型字面量允许在反斜线小括号 `\()` 中插入表达式的值。插入表达式(*interpolated expression*)不能包含未转义的双引号 `"`、反斜线 `\`、回车符或者换行符。表达式值的类型必须在 *String* 类中有对应的初始化方法。
例如,以下所有文本型字面量的值相同:
"1 2 3"
"1 2 \(3)"
"1 2 \(1 + 2)"
var x = 3; "1 2 \(x)"
文本型字面量的默认类型为 `String`。组成字符串的字符类型为 `Character`。更多有关 `String``Character` 的信息请参照 [字符串和字符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-XID_368)。
> 文本型字面量语法
>
> *string-literal* → **"­** [quoted-text](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/quoted-text) **­"­**
>
> *quoted-text* → [quoted-text-item­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/quoted-text-item) [quoted-text](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/quoted-text) ­*opt­*
>
> *quoted-text-item* → [escaped-character­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/escaped-character)
>
> *quoted-text-item* → **\(**­ [expression­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/swift/grammar/expression) **)**­
>
> *quoted-text-item* → 除 `"`、`\`­、`U+000A` 或 `U+000D` 以外的任何 Unicode 扩展字符集
>
> *escaped-character* → **\0­** | **\\**­ | **\t­** | **\n**­ | **\r­** | **\"­** | **\'**­
>
> *escaped-character* → **\x­** [hexadecimal-digit](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit)­ [hexadecimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit)
>
> *escaped-character* → **\u** ­[hexadecimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit) [hexadecimal-digit](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit) [­hexadecimal-digit](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit)­ [hexadecimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit)
>
> *escaped-character* → **\U­** [hexadecimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit) [hexadecimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit) [hexadecimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit) [hexadecimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit) [hexadecimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit) [hexadecimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit) [hexadecimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit) [hexadecimal-digit­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/hexadecimal-digit)
## 运算符
Swift 标准库定义了许多可供使用的运算符,其中大部分在 [基础运算符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-XID_70) 和 [高级运算符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_28) 中进行了阐述。这里将描述哪些字符能用作运算符。
运算符由一个或多个以下字符组成:
`/``=``-``+``!``*``%``<``>``&``|``^``~``.`。也就是说,标记 `=`, `->``//``/*``*/``.` 以及一元前缀运算符 `&` 属于保留字,这些标记不能被重写或用于自定义运算符。
运算符两侧的空白被用来区分该运算符是否为前缀运算符(*prefix operator*)、后缀运算符(*postfix operator*)或二元运算符(*binary operator*)。规则总结如下:
* 如果运算符两侧都有空白或两侧都无空白,将被看作二元运算符。例如:`a+b``a + b` 中的运算符 `+` 被看作二元运算符。
* 如果运算符只有左侧空白,将被看作前缀一元运算符。例如 `a ++b` 中的 `++` 被看作前缀一元运算符。
* 如果运算符只有右侧空白,将被看作后缀一元运算符。例如 `a++ b` 中的 `++` 被看作后缀一元运算符。
* 如果运算符左侧没有空白并紧跟 `.`,将被看作后缀一元运算符。例如 `a++.b` 中的 `++` 被看作后缀一元运算符(同理, `a++ . b` 中的 `++` 是后缀一元运算符而 `a ++ .b` 中的 `++` 不是).
鉴于这些规则,运算符前的字符 `(``[``{` ;运算符后的字符 `)``]``}` 以及字符 `,``;``:` 都将用于空白检测。
以上规则需注意一点,如果运算符 `!``?` 左侧没有空白,则不管右侧是否有空白都将被看作后缀运算符。如果将 `?` 用作可选类型(*optional type*)修饰,左侧必须无空白。如果用于条件运算符 `? :`,必须两侧都有空白。
在特定构成中 ,以 `<``>` 开头的运算符会被分离成两个或多个标记,剩余部分以同样的方式会被再次分离。因此,在 `Dictionary<String, Array<Int>>` 中没有必要添加空白来消除闭合字符 `>` 的歧义。在这个例子中, 闭合字符 `>` 被看作单字符标记,而不会被误解为移位运算符 `>>`
要学习如何自定义新的运算符,请参考 [自定义操作符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_48) 和 [运算符声明](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-XID_644)。学习如何重写现有运算符,请参考 [运算符方法](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_43)。
> 运算符语法
>
> *operator* → [operator-character­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/operator-character) [operator­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/operator) *opt­*
>
> *operator-character* → **/­** | **=­** | **-­** | **+­** | **!­** | ***­** | **%­** | **<­** | **>­** | **&­** | **|­** | **^­** | **~­** | **.­**
>
> *binary-operator* → [operator­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/operator)
>
> *prefix-operator* → [operator­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/operator)
>
> *postfix-operator* → [operator­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/operator)

View File

@ -0,0 +1,272 @@
# 类型Types
---
本页包含内容:
- 类型标注Type Annotation
- 类型标识符Type Identifier
- 元组类型Tuple Type
- 函数类型Function Type
- 数组类型Array Type
- 可选类型Optional Type
- 隐式解析可选类型Implicitly Unwrapped Optional Type
- 协议合成类型Protocol Composition Type
- 元类型Metatype Type
- 类型继承子句Type Inheritance Clause
- 类型推断Type Inference
Swift语言存在两种类型命名型类型和复合型类型。*命名型类型*是指定义时可以给定名字的类型。命名型类型包括类、结构体、枚举和协议。比如,一个用户定义的类`MyClass`的实例拥有类型`MyClass`。除了用户定义的命名型类型Swift标准库也定义了很多常用的命名型类型包括那些表示数组、字典和可选值的类型。
那些通常被其它语言认为是基本或初级的数据型类型Data types——比如表示数字、字符和字符串——实际上就是命名型类型Swift标准库是使用结构体定义和实现它们的。因为它们是命名型类型因此你可以按照“扩展和扩展声明”章节里讨论的那样声明一个扩展来增加它们的行为以适应你程序的需求。
*复合型类型*是没有名字的类型它由Swift本身定义。Swift存在两种复合型类型函数类型和元组类型。一个复合型类型可以包含命名型类型和其它复合型类型。例如元组类型`(Int, (Int, Int))`包含两个元素:第一个是命名型类型`Int`,第二个是另一个复合型类型`(Int, Int)`.
本节讨论Swift语言本身定义的类型并描述Swift中的类型推断行为。
>类型的语法:
*type**array-type* | *function-type* | *type-identifier* | *tuple-type* | *optional-type* | *implicitly-unwrapped-optional-type* | protocol-composition-type | metatype-type
##类型标注
类型标注显式地指定一个变量或表达式的值。类型标注始于冒号`:`终于类型,比如下面两个例子:
```javascript
let someTuple(Double, Double) = (3.14159, 2.71828)
func someFunction(a: Int){ /* ... */ }
```
在第一个例子中,表达式`someTuple`的类型被指定为`(Double, Double)`。在第二个例子中,函数`someFunction`的参数`a`的类型被指定为`Int`
类型标注可以在类型之前包含一个类型特性type attributes的可选列表。
>类型标注的语法:
*type-annotation* → :*attributes*[opt] *type*
##类型标识符
类型标识符引用命名型类型或者是命名型/复合型类型的别名。
大多数情况下,类型标识符引用的是同名的命名型类型。例如类型标识符`Int`引用命名型类型`Int`,同样,类型标识符`Dictionary<String, Int>`引用命名型类型`Dictionary<String, Int>`
在两种情况下类型标识符引用的不是同名的类型。情况一,类型标识符引用的是命名型/复合型类型的类型别名。比如,在下面的例子中,类型标识符使用`Point`来引用元组`(Int, Int)`
```javascript
typealias Point = (Int, Int)
let origin: Point = (0, 0)
```
情况二类型标识符使用dot(`.`)语法来表示在其它模块modules或其它类型嵌套内声明的命名型类型。例如下面例子中的类型标识符引用在`ExampleModule`模块中声明的命名型类型`MyType`
```javascript
var someValue: ExampleModule.MyType
```
>类型标识符的语法:
*type-identifier**type-name generic-argument-clause*[opt] | *type-name generic-argument-clause*[opt].*type-identifier*
*type-name**identifier*
##元组类型
元组类型使用逗号隔开并使用括号括起来的0个或多个类型组成的列表。
你可以使用元组类型作为一个函数的返回类型,这样就可以使函数返回多个值。你也可以命名元组类型中的元素,然后用这些名字来引用每个元素的值。元素的名字由一个标识符和`:`组成。“函数和多返回值”章节里有一个展示上述特性的例子。
`void`是空元组类型`()`的别名。如果括号内只有一个元素,那么该类型就是括号内元素的类型。比如,`(Int)`的类型是`Int`而不是`(Int)`。所以,只有当元组类型包含两个元素以上时才可以标记元组元素。
>元组类型语法:
*tuple* → (*tuple-type-body*[opt])
*tuple-type-body**tuple-type-element-list* ...[opt]
*tuple-type-element-list**tuple-type-element* | *tuple-type-element*, *tuple-type-element-list*
*tuple-type-element**attributes*[opt] **inout** [opt] *type* | **inout** [opt] *element-name type-annotation*
*element-name**identifier*
##函数类型
函数类型表示一个函数、方法或闭包的类型,它由一个参数类型和返回值类型组成,中间用箭头`->`隔开:
- `parameter type` -> `return type`
由于 *参数类型**返回值类型* 可以是元组类型,所以函数类型可以让函数与方法支持多参数与多返回值。
你可以对函数类型应用带有参数类型`()`并返回表达式类型的`auto_closure`属性(见类型属性章节)。一个自动闭包函数捕获特定表达式上的隐式闭包而非表达式本身。下面的例子使用`auto_closure`属性来定义一个很简单的assert函数
```javascript
func simpleAssert(condition: @auto_closure () -> Bool, message: String){
if !condition(){
println(message)
}
}
let testNumber = 5
simpleAssert(testNumber % 2 == 0, "testNumber isn't an even number.")
// prints "testNumber isn't an even number."
```
函数类型可以拥有一个可变长参数作为参数类型中的最后一个参数。从语法角度上讲,可变长参数由一个基础类型名字和`...`组成,如`Int...`。可变长参数被认为是一个包含了基础类型元素的数组。即`Int...`就是`Int[]`。关于使用可变长参数的例子,见章节“可变长参数”。
为了指定一个`in-out`参数,可以在参数类型前加`inout`前缀。但是你不可以对可变长参数或返回值类型使用`inout`。关于In-Out参数的讨论见章节In-Out参数部分。
柯里化函数curried function的类型相当于一个嵌套函数类型。例如下面的柯里化函数`addTwoNumber()()`的类型是`Int -> Int -> Int`
```javascript
func addTwoNumbers(a: Int)(b: Int) -> Int{
return a + b
}
addTwoNumbers(4)(5) // returns 9
```
柯里化函数的函数类型从右向左组成一组。例如,函数类型`Int -> Int -> Int`可以被理解为`Int -> (Int -> Int)`——也就是说,一个函数传入一个`Int`然后输出作为另一个函数的输入,然后又返回一个`Int`。例如,你可以使用如下嵌套函数来重写柯里化函数`addTwoNumbers()()`
```javascript
func addTwoNumbers(a: Int) -> (Int -> Int){
func addTheSecondNumber(b: Int) -> Int{
return a + b
}
return addTheSecondNumber
}
addTwoNumbers(4)(5) // Returns 9
```
>函数类型的语法:
*function-type**type* **->** *type*
##数组类型
Swift语言使用类型名紧接中括号`[]`来简化标准库中定义的命名型类型`Array<T>`。换句话说,下面两个声明是等价的:
```javascript
let someArray: String[] = ["Alex", "Brian", "Dave"]
let someArray: Array<String> = ["Alex", "Brian", "Dave"]
```
上面两种情况下,常量`someArray`都被声明为字符串数组。数组的元素也可以通过`[]`获取访问:`someArray[0]`是指第0个元素`“Alex”`
上面的例子同时显示,你可以使用`[]`作为初始值构造数组,空的`[]`则用来来构造指定类型的空数组。
```javascript
var emptyArray: Double[] = []
```
你也可以使用链接起来的多个`[]`集合来构造多维数组。例如,下例使用三个`[]`集合来构造三维整型数组:
```javascript
var array3D: Int[][][] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
```
访问一个多维数组的元素时,最左边的下标指向最外层数组的相应位置元素。接下来往右的下标指向第一层嵌入的相应位置元素,依次类推。这就意味着,在上面的例子中,`array3D[0]`是指`[[1, 2], [3, 4]]``array3D[0][1]`是指`[3, 4]``array3D[0][1][1]`则是指值`4`
关于Swift标准库中`Array`类型的细节讨论见章节Arrays。
>数组类型的语法:
*array-type**type*`[ ]` | *array-type*`[ ]`
##可选类型
Swift定义后缀`?`来作为标准库中的定义的命名型类型`Optional<T>`的简写。换句话说,下面两个声明是等价的:
```javascript
var optionalInteger: Int?
var optionalInteger: Optional<Int>
```
在上述两种情况下,变量`optionalInteger`都被声明为可选整型类型。注意在类型和`?`之间没有空格。
类型`Optional<T>`是一个枚举,有两种形式,`None``Some(T)`,又来代表可能出现或可能不出现的值。任意类型都可以被显式的声明(或隐式的转换)为可选类型。当声明一个可选类型时,确保使用括号给`?`提供合适的作用范围。比如说,声明一个整型的可选数组,应写作`(Int[])?`,写成`Int[]?`的话则会出错。
如果你在声明或定义可选变量或特性的时候没有提供初始值,它的值则会自动赋成缺省值`nil`
可选符合`LogicValue`协议,因此可以出现在布尔值环境下。此时,如果一个可选类型`T?`实例包含有类型为`T`的值(也就是说值为`Optional.Some(T)`),那么此可选类型就为`true`,否则为`false`
如果一个可选类型的实例包含一个值,那么你就可以使用后缀操作符`!`来获取该值,正如下面描述的:
```javascript
optionalInteger = 42
optionalInteger! // 42
```
使用`!`操作符获取值为`nil`的可选项会导致运行错误runtime error
你也可以使用可选链和可选绑定来选择性的执行可选表达式上的操作。如果值为`nil`,不会执行任何操作因此也就没有运行错误产生。
更多细节以及更多如何使用可选类型的例子,见章节“可选”。
>可选类型语法:
*optional-type**type*?
##隐式解析可选类型
Swift语言定义后缀`!`作为标准库中命名类型`ImplicitlyUnwrappedOptional<T>`的简写。换句话说,下面两个声明等价:
```javascript
var implicitlyUnwrappedString: String!
var implicitlyUnwrappedString: ImplicitlyUnwrappedOptional<String>
```
上述两种情况下,变量`implicitlyUnwrappedString`被声明为一个隐式解析可选类型的字符串。注意类型与`!`之间没有空格。
你可以在使用可选的地方同样使用隐式解析可选。比如,你可以将隐式解析可选的值赋给变量、常量和可选特性,反之亦然。
有了可选,你在声明隐式解析可选变量或特性的时候就不用指定初始值,因为它有缺省值`nil`
由于隐式解析可选的值会在使用时自动解析,所以没必要使用操作符`!`来解析它。也就是说,如果你使用值为`nil`的隐式解析可选,就会导致运行错误。
使用可选链会选择性的执行隐式解析可选表达式上的某一个操作。如果值为`nil`,就不会执行任何操作,因此也不会产生运行错误。
关于隐式解析可选的更多细节,见章节“隐式解析可选”。
>隐式解析可选的语法:
implicitly-unwrapped-optional-type → type!
##协议合成类型
协议合成类型是一种符合每个协议的指定协议列表类型。协议合成类型可能会用在类型标注和泛型参数中。
协议合成类型的形式如下:
```javascript
protocol<Protocol 1, Procotol 2>
```
协议合成类型允许你指定一个值,其类型可以适配多个协议的条件,而且不需要定义一个新的命名型协议来继承其它想要适配的各个协议。比如,协议合成类型`protocol<Protocol A, Protocol B, Protocol C>`等效于一个从`Protocol A``Protocol B` `Protocol C`继承而来的新协议`Protocol D`,很显然这样做有效率的多,甚至不需引入一个新名字。
协议合成列表中的每项必须是协议名或协议合成类型的类型别名。如果列表为空,它就会指定一个空协议合成列表,这样每个类型都能适配。
>协议合成类型的语法:
*protocol-composition-type***protocol** <*protocol-identifier-list[opt]*>
*protocol-identifier-list**protocol-identifier* | *protocol-identifier, protocol-identifier-list*
*protocol-identifier**type-identifier*
##元类型
元类型是指所有类型的类型,包括类、结构体、枚举和协议。
类、结构体或枚举类型的元类型是相应的类型名紧跟`.Type`。协议类型的元类型——并不是运行时适配该协议的具体类型——是该协议名字紧跟`.Protocol`。比如,类`SomeClass`的元类型就是`SomeClass.Type`,协议`SomeProtocol`的元类型就是`SomeProtocal.Protocol`
你可以使用后缀`self`表达式来获取类型。比如,`SomeClass.self`返回`SomeClass`本身,而不是`SomeClass`的一个实例。同样,`SomeProtocol.self`返回`SomeProtocol`本身,而不是运行时适配`SomeProtocol`的某个类型的实例。还可以对类型的实例使用`dynamicType`表达式来获取该实例在运行阶段的类型,如下所示:
```javascript
class SomeBaseClass {
class func printClassName() {
println("SomeBaseClass")
}
}
class SomeSubClass: SomeBaseClass {
override class func printClassName() {
println("SomeSubClass")
}
}
let someInstance: SomeBaseClass = SomeSubClass()
// someInstance is of type SomeBaseClass at compile time, but
// someInstance is of type SomeSubClass at runtime
someInstance.dynamicType.printClassName()
// prints "SomeSubClass
```
>元类型的语法:
*metatype-type**type*.**Type** | *type*.**Protocol**
##类型继承子句
类型继承子句被用来指定一个命名型类型继承哪个类且适配哪些协议。类型继承子句开始于冒号`:`,紧跟由`,`隔开的类型标识符列表。
类可以继承单个超类,适配任意数量的协议。当定义一个类时,超类的名字必须出现在类型标识符列表首位,然后跟上该类需要适配的任意数量的协议。如果一个类不是从其它类继承而来,那么列表可以以协议开头。关于类继承更多的讨论和例子,见章节“继承”。
其它命名型类型可能只继承或适配一个协议列表。协议类型可能继承于其它任意数量的协议。当一个协议类型继承于其它协议时,其它协议的条件集合会被集成在一起,然后其它从当前协议继承的任意类型必须适配所有这些条件。
枚举定义中的类型继承子句可以是一个协议列表,或是指定原始值的枚举,一个单独的指定原始值类型的命名型类型。使用类型继承子句来指定原始值类型的枚举定义的例子,见章节“原始值”。
>类型继承子句的语法:
*type-inheritance-clause* → :*type-inheritance-list*
*type-inheritance-list**type-identifier* | *type-identifier*, *type-inheritance-list*
##类型推断
Swift广泛的使用类型推断从而允许你可以忽略很多变量和表达式的类型或部分类型。比如对于`var x: Int = 0`,你可以完全忽略类型而简写成`var x = 0`——编译器会正确的推断出`x`的类型`Int`。类似的,当完整的类型可以从上下文推断出来时,你也可以忽略类型的一部分。比如,如果你写了`let dict: Dictionary = ["A": 1]`,编译提也能推断出`dict`的类型是`Dictionary<String, Int>`
在上面的两个例子中类型信息从表达式树expression tree的叶子节点传向根节点。也就是说`var x: Int = 0``x`的类型首先根据`0`的类型进行推断,然后将该类型信息传递到根节点(变量`x`)。
在Swift中类型信息也可以反方向流动——从根节点传向叶子节点。在下面的例子中常量`eFloat`上的显式类型标注(`:Float`)导致数字字面量`2.71828`的类型是`Float`而非`Double`
```javascript
let e = 2.71828 // The type of e is inferred to be Double.
let eFloat: Float = 2.71828 // The type of eFloat is Float.
```
Swift中的类型推断在单独的表达式或语句水平上进行。这意味着所有用于推断类型的信息必须可以从表达式或其某个子表达式的类型检查中获取。

View File

@ -0,0 +1,106 @@
# 泛型参数
---------
本页包含内容:
* <a href="#label1">泛型形参语句</a>
* <a href="#label2">泛型实参语句</a>
本节涉及泛型类型、泛型函数以及泛型构造器的参数,包括形参和实参。声明泛型类型、函数或构造器时,须指定相应的类型参数。类型参数相当于一个占位符,当实例化泛型类型、调用泛型函数或泛型构造器时,就用具体的类型实参替代之。
关于 Swift 语言的泛型概述,见[泛型](../charpter2/22_Generics.md)(第二部分第22章)。
## <a name="label1">泛型实参语句</a>
泛型形参语句指定泛型类型或函数的类型形参,以及这些参数的关联约束和要求。泛型形参语句用尖括号(<>)包住,并且有以下两种声明形式:
<generic parameter list>
<generic parameter list where requirements >
泛型形参列表中泛型形参用逗号分开,每一个采用以下形式:
type parameter : constrain
泛型形参由两部分组成类型形参及其后的可选约束。类型形参只是占位符类型如TUVKeyTypeValueType等的名字而已。你可以在泛型类型、函数的其余部分或者构造器声明以及函数或构造器的签名中使用它。
约束用于指明该类型形参继承自某个类或者遵守某个协议或协议的一部分。例如,在下面的泛型中,泛型形参`T: Comparable`表示任何用于替代类型形参`T`的类型实参必须满足`Comparable`协议。
func simpleMin<T: COmparable>(x: T, y: T) -> T {
if x < y {
return y
}
return x
}
`Int``Double`均满足`Comparable`协议该函数接受任何一种类型与泛型类型相反调用泛型函数或构造器时不需要指定泛型实参语句类型实参由传递给函数或构造器的实参推断而出
simpleMin(17, 42) // T is inferred to be Int
simpleMin(3.14159, 2.71828) // T is inferred to be Double
## Where语句
要想对类型形参及其关联类型指定额外要求可以在泛型形参列表之后添加`where`语句`where`语句由关键字`where`及其后的用逗号分割的多个要求组成
`where`语句中的要求用于指明该类型形参继承自某个类或遵守某个协议或协议的一部分尽管`where`语句有助于表达类型形参上的简单约束`T: Comparable`等同于`T where T: Comparable`等等但是依然可以用来对类型形参及其关联约束提供更复杂的约束`<T where T: C, T: P>`表示泛型类型`T`继承自类`C`且遵守协议`P`
如上所述可以强制约束类型形参的关联类型遵守某个协议`<T: Generator where T.Element: Equatable>`表示`T`遵守`Generator`协议而且`T`的关联类型`T.Element`遵守`Eauatable`协议`T`有关联类型是因为`Generator`声明了`Element``T`遵守`Generator`协议)。
也可以用操作符`==`来指定两个类型等效的要求例如有这样一个约束`T``U`遵守`Generator`协议同时要求它们的关联类型等同可以这样来表达`<T: Generator, U: Generator where T.Element == U.Element>`
当然替代类型形参的类型实参必须满足所有类型形参所要求的约束和要求
泛型函数或构造器可以重载但在泛型形参语句中的类型形参必须有不同的约束或要求抑或二者皆不同当调用重载的泛型函数或构造器时编译器会用这些约束来决定调用哪个重载函数或构造器
泛型类可以生成一个子类但是这个子类也必须是泛型类
> Grammar of a generic parameter clause
> parameter-clause → <­generic-parameter-list­requirement-clause >
>
>­generic-parameter-list → generic-parameter­ generic-parameter­,­generic-parameter-list ­
>
> generic-parameter → type-name­
>
> generic-parameter → type-name­:­type-identifier­
>
> generic-parameter → type-name­:­protocol-composition-type­
> requirement-clause → `where`­requirement-list­
>
> requirement-list → requirement­ requirement­,­requirement-list­
>
> requirement → conformance-requirement­ same-type-requirement­
> conformance-requirement → type-identifier­:­type-identifier­
>
> conformance-requirement → type-identifier­:­protocol-composition-type­
>
> same-type-requirement → type-identifier­==­type-identifier
## <a name="label2">泛型实参语句</a>
泛型实参语句指定泛型类型的类型实参泛型实参语句用尖括号<>)包住,并且按如下形式声明:
< generic argument list >
泛型实参列表中类型实参有逗号分开。类型实参是实际具体类型的名字用来替代泛型类型的泛型形参语句中的相应的类型形参。从而得到泛型类型的一个特化版本。如Swift标准库的泛型字典类型定义如下
struct Dictionary<KeyTypel: Hashable, ValueType>: Collection,
DictionaryLiteralConvertible {
/* .. */
}
泛型`Dictionary`类型的特化版本,`Dictionary<String, Int>`就是用具体的`String``Int`类型替代泛型类型`KeyType: Hashable``ValueType`产生的。每一个类型实参必须满足它所替代的泛型形参的所有约束,包括任何`where`语句所指定的额外的要求。上面的例子中,类型形参`KeyType`要求满足`Hashable`协议,因此`String`也必须满足`Hashable`协议。
可以用本身就是泛型类型的特化版本的类型实参替代类型形参(假设已满足合适的约束和要求)。例如,为了生成一个元素类型是整型数组的数组,可以用数组的特化版本`Array<Int>`替代泛型类型`Array<T>`的类型形参`T`来实现。
let arrayOfArrays: Array<Array<Int>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
<a href="#label1">泛型形参语句</a>一样,不能用泛型实参语句来指定泛型函数或构造器的类型实参。
> Grammar of a generic argument clause
> generic-argument-clause → <­generic-argument-list­>­
> generic-argument-list → generic-argument­ generic-argument­,­generic-argument-list­
> generic-argument → type