make gitbook
This commit is contained in:
@ -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("The width of someResolution is \(someResolution.width)")
|
||||
// 输出 "The width of someResolution is 0"
|
||||
</code></pre>
|
||||
@ -693,7 +715,7 @@ var cinema = hd
|
||||
<pre><code class="lang-swift">println("hd is still \(hd.width ) pixels wide")
|
||||
// 输出 "hd is still 1920 pixels wide"
|
||||
</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("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
|
||||
// 输出 "The frameRate property of theEighty is now 30.0"
|
||||
</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
|
||||
}
|
||||
//输出 "tenEighty and alsoTenEighty refer to the same Resolution instance."
|
||||
</code></pre>
|
||||
<p>请注意“等价于”(用三个等号表示,===) 与“等于”(用两个等号表示,==)的不同:</p>
|
||||
<p>请注意<code>“等价于"</code>(用三个等号表示,===) 与<code>“等于"</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])
|
||||
// 输出 "These two subarrays share the same elements."
|
||||
</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 = ["Mohsen", "Hilary", "Justyn", "Amy", "Rich", "Graham", "Vic"]
|
||||
var copiedNames = names.copy()
|
||||
</code></pre>
|
||||
<p>我们可以通过修改一个数组中某元素,并且检查另一个数组中对应元素的方法来判定<code>names</code>数组确已被复制。如果你将<code>copiedNames</code>中第一个元素从"<code>Mohsen</code>"修改为"<code>Mo</code>",则<code>names</code>数组返回的仍是拷贝发生前的"<code>Mohsen</code>":</p>
|
||||
<p>我们可以通过修改数组中某一个元素,并且检查另一个数组中对应元素的方法来判定<code>names</code>数组确已被复制。如果你将<code>copiedNames</code>中第一个元素从"<code>Mohsen</code>"修改为"<code>Mo</code>",则<code>names</code>数组返回的仍是拷贝发生前的"<code>Mohsen</code>":</p>
|
||||
<pre><code class="lang-swift">copiedName[0] = "Mo"
|
||||
println(name[0])
|
||||
// 输出 "Mohsen"
|
||||
|
||||
Reference in New Issue
Block a user