make gitbook

This commit is contained in:
numbbbbb
2014-06-16 22:40:12 +08:00
parent 97083324b6
commit bfe0553db8
43 changed files with 1046 additions and 193 deletions

View File

@ -16,6 +16,8 @@
<meta name="author" content="https:">
<link rel="next" href="../chapter2/10_Properties.html" />
@ -32,12 +34,12 @@
<div class="book" data-level="2.9" data-basepath=".." data-revision="1402903834498">
<div class="book" data-github="https://github.com/numbbbbb/the-swift-programming-language-in-chinese" data-level="2.9" data-basepath=".." data-revision="1402929590291">
<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>
<a href="https://github.com/null" target="_blank" class="btn pull-left home-bookmark" aria-label="GitHub home"><i class="fa fa-bookmark-o"></i></a>
<a href="https://github.com/https://github.com/numbbbbb/the-swift-programming-language-in-chinese" target="_blank" class="btn pull-left home-bookmark" aria-label="GitHub home"><i class="fa fa-bookmark-o"></i></a>
<a href="#" class="btn pull-left toggle-search" aria-label="Toggle search"><i class="fa fa-search"></i></a>
<span id="font-settings-wrapper">
@ -80,6 +82,9 @@
<a href="https://github.com/https://github.com/numbbbbb/the-swift-programming-language-in-chinese/stargazers" target="_blank" class="btn pull-right count-star hidden-xs"><i class="fa fa-star-o"></i> Star (<span>-</span>)</a>
<a href="https://github.com/https://github.com/numbbbbb/the-swift-programming-language-in-chinese/watchers" target="_blank" class="btn pull-right count-watch hidden-xs"><i class="fa fa-eye"></i> Watch (<span>-</span>)</a>
<!-- Title -->
<h1>
@ -97,12 +102,29 @@
<ul class="summary">
<li>
<a href="https://github.com/https:" target="blank" class="author-link">About the author</a>
</li>
<li>
<a href="https://github.com/https://github.com/numbbbbb/the-swift-programming-language-in-chinese/issues" target="blank"class="issues-link">Questions and Issues</a>
</li>
<li>
<a href="https://github.com/https://github.com/numbbbbb/the-swift-programming-language-in-chinese/edit/master/chapter2/09_Classes_and_Structures.md" target="blank" class="contribute-link">Edit and Contribute</a>
</li>
<li class="divider"></li>
<li data-level="0" data-path="index.html">
<a href="../"><i class="fa fa-check"></i></a>
@ -573,7 +595,7 @@
<div class="page-inner">
<section class="normal" id="section-gitbook_106">
<section class="normal" id="section-gitbook_25">
<blockquote>
<p>翻译:<a href="https://github.com/JaySurplus" target="_blank">JaySurplus</a><br>校对:<a href="https://github.com/sg552" target="_blank">sg552</a></p>
@ -587,7 +609,7 @@
<li><a href="#choosing_between_classes_and_structures">类和结构体的选择</a></li>
<li><a href="#assignment_and_copy_behavior_for_collection_types">集合collection类型的赋值与复制行为</a></li>
</ul>
<p>类和结构体是人们构建代码所用的一种通用且灵活的构造体。为了在类和结构体中实现各种功能,我们必须要严格按照对于常量变量以及函数所规定的语法规则来定义属性和添加方法。</p>
<p>类和结构体是人们构建代码所用的一种通用且灵活的构造体。为了在类和结构体中实现各种功能,我们必须要严格按照常量变量以及函数所规定的语法规则来定义属性和添加方法。</p>
<p>与其他编程语言所不同的是Swift 并不要求你为自定义类和结构去创建独立的接口和实现文件。你所要做的是在一个单一文件中定义一个类或者结构体,系统将会自动生成面向其它代码的外部接口。</p>
<blockquote>
<p> 注意:<br>通常一个<code></code>的实例被称为<code>对象</code>。然而在Swift 中,类和结构体的关系要比在其他语言中更加的密切,本章中所讨论的大部分功能都可以用在类和结构体上。因此,我们会主要使用<code>实例</code>而不是<code>对象</code></p>
@ -596,7 +618,7 @@
<h3 id="-">类和结构体对比</h3>
<p>Swift 中类和结构体有很多共同点。共同处在于:</p>
<ul>
<li>定义属性用于存值</li>
<li>定义属性用于存</li>
<li>定义方法用于提供功能</li>
<li>定义附属脚本用于访问值</li>
<li>定义构造器用于生成初始化值</li>
@ -639,8 +661,8 @@ class VideoMode {
var name: String?
}
</code></pre>
<p>在上面的示例中我们定义了一个名为<code>Resolution</code>的结构体,用来描述一个显示器的像素分辨率。这个结构体包含了两个名为<code>width</code><code>height</code>存属性。存属性是捆绑和存在类或结构体中的常量或变量。当这两个属性被初始化为整数<code>0</code>的时候,它们会被推断为<code>Int</code>类型。</p>
<p>在上面的示例中我们还定义了一个名为<code>VideoMode</code>的类,用来描述一个视频显示器的特定模式。这个类包含了四个储存属性变量。第一个是<code>分辨率</code>,它被初始化为一个新的<code>Resolution</code>结构体的实例,具有<code>Resolution</code>的属性类型。新<code>VideoMode</code>实例同时还会初始化其它三个属性,它们分别是,初始值为<code>false</code>(意为“non-interlaced video”)的<code>interlaced</code>,回放帧率初始值为<code>0.0</code><code>frameRate</code>和值为可选<code>String</code><code>name</code><code>name</code>属性会被自动赋予一个默认值<code>nil</code>,意为“没有<code>name</code>值”,因它是一个可选类型。</p>
<p>在上面的示例中我们定义了一个名为<code>Resolution</code>的结构体,用来描述一个显示器的像素分辨率。这个结构体包含了两个名为<code>width</code><code>height</code>的存属性。存属性是捆绑和存在类或结构体中的常量或变量。当这两个属性被初始化为整数<code>0</code>的时候,它们会被推断为<code>Int</code>类型。</p>
<p>在上面的示例中我们还定义了一个名为<code>VideoMode</code>的类,用来描述一个视频显示器的特定模式。这个类包含了四个储存属性变量。第一个是<code>分辨率</code>,它被初始化为一个新的<code>Resolution</code>结构体的实例,具有<code>Resolution</code>的属性类型。新<code>VideoMode</code>实例同时还会初始化其它三个属性,它们分别是,初始值为<code>false</code>(意为“non-interlaced video”)的<code>interlaced</code>,回放帧率初始值为<code>0.0</code><code>frameRate</code>和值为可选<code>String</code><code>name</code><code>name</code>属性会被自动赋予一个默认值<code>nil</code>,意为“没有<code>name</code>值”,因它是一个可选类型。</p>
<h3 id="-">类和结构体实例</h3>
<p><code>Resolution</code>结构体和<code>VideoMode</code>类的定义仅描述了什么是<code>Resolution</code><code>VideoMode</code>。它们并没有描述一个特定的分辨率resolution或者视频模式video mode。为了描述一个特定的分辨率或者视频模式我们需要生成一个它们的实例。</p>
<p>生成结构体和类实例的语法非常相似:</p>
@ -649,7 +671,7 @@ let someVideoMode = VideoMode()
</code></pre>
<p>结构体和类都使用构造器语法来生成新的实例。构造器语法的最简单形式是在结构体或者类的类型名称后跟随一个空括弧,如<code>Resolution()</code><code>VideoMode()</code>。通过这种方式所创建的类或者结构体实例,其属性均会被初始化为默认值。<a href="14_Initialization.html">构造过程</a>章节会对类和结构体的初始化进行更详细的讨论。</p>
<h3 id="-">属性访问</h3>
<p>通过使用<em>点语法</em><em>dot syntax</em>,你可以访问实例中所含有的属性。其语法规则是,实例名后面紧跟属性名,两者通过点号(.)连接:</p>
<p>通过使用<em>点语法</em><em>dot syntax</em>你可以访问实例中所含有的属性。其语法规则是,实例名后面紧跟属性名,两者通过点号(.)连接:</p>
<pre><code class="lang-swift">println(&quot;The width of someResolution is \(someResolution.width)&quot;)
// 输出 &quot;The width of someResolution is 0&quot;
</code></pre>
@ -693,7 +715,7 @@ var cinema = hd
<pre><code class="lang-swift">println(&quot;hd is still \(hd.width ) pixels wide&quot;)
// 输出 &quot;hd is still 1920 pixels wide&quot;
</code></pre>
<p>在将<code>hd</code>赋予给<code>cinema</code>的时候,实际上是将<code>hd</code>中所存的<code>values</code>进行拷贝,然后将拷贝的数据存到新的<code>cinema</code>实例中。结果就是两个完全独立的实例碰巧包含有相同的数值。由于两者相互独立,因此将<code>cinema</code><code>width</code>修改为<code>2048</code>并不会影响<code>hd</code>中的宽width</p>
<p>在将<code>hd</code>赋予给<code>cinema</code>的时候,实际上是将<code>hd</code>中所存<code>values</code>进行拷贝,然后将拷贝的数据存到新的<code>cinema</code>实例中。结果就是两个完全独立的实例碰巧包含有相同的数值。由于两者相互独立,因此将<code>cinema</code><code>width</code>修改为<code>2048</code>并不会影响<code>hd</code>中的宽width</p>
<p>枚举也遵循相同的行为准则:</p>
<pre><code class="lang-swift">enum CompassPoint {
case North, South, East, West
@ -709,7 +731,7 @@ if rememberDirection == .West {
<p>上例中<code>rememberedDirection</code>被赋予了<code>currentDirection</code>的值value实际上它被赋予的是值value的一个拷贝。赋值过程结束后再修改<code>currentDirection</code>的值并不影响<code>rememberedDirection</code>所储存的原始值value的拷贝。</p>
<p><a name="classes_are_reference_types"></a></p>
<h2 id="-">类是引用类型</h2>
<p>与值类型不同,引用类型在被赋予到一个变量常量或者被传递到一个函数时,操作的并不是拷贝。因此,引用的是已存在的实例本身而不是其拷贝。</p>
<p>与值类型不同,引用类型在被赋予到一个变量常量或者被传递到一个函数时,操作的是引用,其并不是拷贝。因此,引用的是已存在的实例本身而不是其拷贝。</p>
<p>请看下面这个示例,其使用了之前定义的<code>VideoMode</code>类:</p>
<pre><code class="lang-swift">let tenEighty = VideoMode()
tenEighty.resolution = hd
@ -722,14 +744,14 @@ tenEighty.frameRate = 25.0
<pre><code class="lang-swift">let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
</code></pre>
<p>因为类是引用类型,所以<code>tenEight</code><code>alsoTenEight</code>实际上引用的是相同的<code>VideoMode</code>实例。换句话说,它们是同一个实例的两种叫法。</p>
<p>因为类是引用类型,所以<code>tenEight</code><code>alsoTenEight</code>实际上引用的是相同的<code>VideoMode</code>实例。换句话说,它们是同一个实例的两种叫法。</p>
<p>下面,通过查看<code>tenEighty</code><code>frameRate</code>属性,我们会发现它正确的显示了基本<code>VideoMode</code>实例的新帧率,其值为<code>30.0</code></p>
<pre><code class="lang-swift">println(&quot;The frameRate property of tenEighty is now \(tenEighty.frameRate)&quot;)
// 输出 &quot;The frameRate property of theEighty is now 30.0&quot;
</code></pre>
<p>需要注意的是<code>tenEighty</code><code>alsoTenEighty</code>被声明为<em>常量constants</em>而不是变量。然而你依然可以改变<code>tenEighty.frameRate</code><code>alsoTenEighty.frameRate</code>,因为这两个常量本身不会改变。它们并不<code></code>这个<code>VideoMode</code>实例,在后台仅仅是对<code>VideoMode</code>实例的引用。所以,改变的是被引用的基础<code>VideoMode</code><code>frameRate</code>参数,而不改变常量的值。</p>
<p>需要注意的是<code>tenEighty</code><code>alsoTenEighty</code>被声明为<em>常量constants</em>而不是变量。然而你依然可以改变<code>tenEighty.frameRate</code><code>alsoTenEighty.frameRate</code>,因为这两个常量本身不会改变。它们并不<code></code>这个<code>VideoMode</code>实例,在后台仅仅是对<code>VideoMode</code>实例的引用。所以,改变的是被引用的基础<code>VideoMode</code><code>frameRate</code>参数,而不改变常量的值。</p>
<h3 id="-">恒等运算符</h3>
<p>因为类是引用类型,有可能有多个常量和变量在后台同时引用某一个类实例。(对于结构体和枚举来说,这并不成立。因为它们作值类型,在被赋予到常量变量或者传递到函数时,总是会被拷贝。)</p>
<p>因为类是引用类型,有可能有多个常量和变量在后台同时引用某一个类实例。(对于结构体和枚举来说,这并不成立。因为它们作值类型,在被赋予到常量变量或者传递到函数时,其值总是会被拷贝。)</p>
<p>如果能够判定两个常量或者变量是否引用同一个类实例将会很有帮助。为了达到这个目的Swift 内建了两个恒等运算符:</p>
<ul>
<li>等价于 === </li>
@ -741,7 +763,7 @@ alsoTenEighty.frameRate = 30.0
}
//输出 &quot;tenEighty and alsoTenEighty refer to the same Resolution instance.&quot;
</code></pre>
<p>请注意“等价于”(用三个等号表示,=== 与“等于”(用两个等号表示,==)的不同:</p>
<p>请注意<code>“等价于&quot;</code>(用三个等号表示,===<code>“等于&quot;</code>(用两个等号表示,==)的不同:</p>
<ul>
<li>“等价于”表示两个类类型class type的常量或者变量引用同一个类实例。</li>
<li>“等于”表示两个实例的值“相等”或“相同”,判定时要遵照类设计者定义定义的评判标准,因此相比于“相等”,这是一种更加合适的叫法。</li>
@ -752,7 +774,7 @@ alsoTenEighty.frameRate = 30.0
<p><a name="choosing_between_classes_and_structures"></a></p>
<h2 id="-">类和结构体的选择</h2>
<p>在你的代码中,你可以使用类和结构体来定义你的自定义数据类型。</p>
<p>然而,结构体实例总是通过值传递,类实例总是通过引用传递。这意味两者适用不同的任务。当你在考虑一个工程项目的数据构造和功能的时候,你需要决定每个数据构造是定义成类还是结构体。</p>
<p>然而,结构体实例总是通过值传递,类实例总是通过引用传递。这意味两者适用不同的任务。当你在考虑一个工程项目的数据构造和功能的时候,你需要决定每个数据构造是定义成类还是结构体。</p>
<p>按照通用的准则,当符合一条或多条以下条件时,请考虑构建结构体:</p>
<ul>
<li>结构体的主要目的是用来封装少量相关简单数据值。</li>
@ -861,12 +883,12 @@ println(c[0])
// 输出 &quot;These two subarrays share the same elements.&quot;
</code></pre>
<h3 id="-">强制复制数组</h3>
<p>我们通过调用数组的<code>copy</code>方法进行强制显复制。这个方法对数组进行了浅拷贝shallow copy,并且返回一个包含此拷贝的新数组。</p>
<p>我们通过调用数组的<code>copy</code>方法进行强制显复制。这个方法对数组进行了浅拷贝shallow copy并且返回一个包含此拷贝数组的新数组。</p>
<p>下面这个示例中定义了一个<code>names</code>数组,其包含了七个人名。还定义了一个<code>copiedNames</code>变量,用以储存在<code>names</code>上调用<code>copy</code>方法所返回的结果:</p>
<pre><code class="lang-swift">var names = [&quot;Mohsen&quot;, &quot;Hilary&quot;, &quot;Justyn&quot;, &quot;Amy&quot;, &quot;Rich&quot;, &quot;Graham&quot;, &quot;Vic&quot;]
var copiedNames = names.copy()
</code></pre>
<p>我们可以通过修改一个数组中某元素,并且检查另一个数组中对应元素的方法来判定<code>names</code>数组确已被复制。如果你将<code>copiedNames</code>中第一个元素从&quot;<code>Mohsen</code>&quot;修改为&quot;<code>Mo</code>&quot;,则<code>names</code>数组返回的仍是拷贝发生前的&quot;<code>Mohsen</code>&quot;</p>
<p>我们可以通过修改数组中某一个元素,并且检查另一个数组中对应元素的方法来判定<code>names</code>数组确已被复制。如果你将<code>copiedNames</code>中第一个元素从&quot;<code>Mohsen</code>&quot;修改为&quot;<code>Mo</code>&quot;,则<code>names</code>数组返回的仍是拷贝发生前的&quot;<code>Mohsen</code>&quot;</p>
<pre><code class="lang-swift">copiedName[0] = &quot;Mo&quot;
println(name[0])
// 输出 &quot;Mohsen&quot;