From 12ba3ad90cc0390160370e591912eaa789764b41 Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 19:05:10 +0800 Subject: [PATCH 01/14] fix 2.16 automatic reference counting --- .../16_Automatic_Reference_Counting.md | 431 ++++++++++-------- 1 file changed, 243 insertions(+), 188 deletions(-) diff --git a/source/chapter2/16_Automatic_Reference_Counting.md b/source/chapter2/16_Automatic_Reference_Counting.md index 30522b37..5f730efa 100644 --- a/source/chapter2/16_Automatic_Reference_Counting.md +++ b/source/chapter2/16_Automatic_Reference_Counting.md @@ -1,25 +1,23 @@ -> 翻译:TimothyYe - -> 校对:Hawstein +> 翻译:TimothyYe +> 校对:Hawstein # 自动引用计数 ----------------- 本页包含内容: -- [自动引用计数的工作机制](#how_arc_works) -- [自动引用计数实践](#arc_in_action) -- [类实例之间的循环强引用](#strong_reference_cycles_between_class_instances) -- [解决实例之间的循环强引用](#resolving_strong_reference_cycles_between_class_instances) -- [闭包引起的循环强引用](#strong_reference_cycles_for_closures) -- [解决闭包引起的循环强引用](#resolving_strong_reference_cycles_for_closures) +- [自动引用计数的工作机制](#how_arc_works) +- [自动引用计数实践](#arc_in_action) +- [类实例之间的循环强引用](#strong_reference_cycles_between_class_instances) +- [解决实例之间的循环强引用](#resolving_strong_reference_cycles_between_class_instances) +- [闭包引起的循环强引用](#strong_reference_cycles_for_closures) +- [解决闭包引起的循环强引用](#resolving_strong_reference_cycles_for_closures) Swift 使用自动引用计数(ARC)这一机制来跟踪和管理你的应用程序的内存。通常情况下,Swift 的内存管理机制会一直起着作用,你无须自己来考虑内存的管理。ARC 会在类的实例不再被使用时,自动释放其占用的内存。 然而,在少数情况下,ARC 为了能帮助你管理内存,需要更多的关于你的代码之间关系的信息。本章描述了这些情况,并且为你示范怎样启用 ARC 来管理你的应用程序的内存。 -> 注意: -> +> 注意: 引用计数仅仅应用于类的实例。结构体和枚举类型是值类型,不是引用类型,也不是通过引用的方式存储和传递。 @@ -38,31 +36,35 @@ Swift 使用自动引用计数(ARC)这一机制来跟踪和管理你的应 下面的例子展示了自动引用计数的工作机制。例子以一个简单的`Person`类开始,并定义了一个叫`name`的常量属性: - class Person { - let name: String - - init(name: String) { - self.name = name - println("\(name) is being initialized") - } - - deinit { - println("\(name) is being deinitialized") - } - } +```swift +class Person { + let name: String + init(name: String) { + self.name = name + println("\(name) is being initialized") + } + deinit { + println("\(name) is being deinitialized") + } +} +``` `Person`类有一个构造函数,此构造函数为实例的`name`属性赋值并打印出信息,以表明初始化过程生效。`Person`类同时也拥有析构函数,同样会在实例被销毁的时候打印出信息。 接下来的代码片段定义了三个类型为`Person?`的变量,用来按照代码片段中的顺序,为新的`Person`实例建立多个引用。由于这些变量是被定义为可选类型(Person?,而不是Person),它们的值会被自动初始化为`nil`,目前还不会引用到`Person`类的实例。 - var reference1: Person? - var reference2: Person? - var reference3: Person? +```swift +var reference1: Person? +var reference2: Person? +var reference3: Person? +``` 现在你可以创建`Person`类的新实例,并且将它赋值给三个变量其中的一个: - reference1 = Person(name: "John Appleseed") - // prints "John Appleseed is being initialized” +```swift +reference1 = Person(name: "John Appleseed") +// prints "John Appleseed is being initialized” +``` 应当注意到当你调用`Person`类的构造函数的时候,"John Appleseed is being initialized”会被打印出来。由此可以确定构造函数被执行。 @@ -70,20 +72,26 @@ Swift 使用自动引用计数(ARC)这一机制来跟踪和管理你的应 如果你将同样的`Person`实例也赋值给其他两个变量,该实例又会多出两个强引用: - reference2 = reference1 - reference3 = reference1 +```swift +reference2 = reference1 +reference3 = reference1 +``` 现在这个`Person`实例已经有三个强引用了。 如果你通过给两个变量赋值`nil`的方式断开两个强引用()包括最先的那个强引用),只留下一个强引用,`Person`实例不会被销毁: - reference2 = nil - reference3 = nil +```swift +reference2 = nil +reference3 = nil +``` ARC 会在第三个,也即最后一个强引用被断开的时候,销毁`Person`实例,这也意味着你不再使用这个`Person`实例: - reference3 = nil - // prints "John Appleseed is being deinitialized" +```swift +reference3 = nil +// prints "John Appleseed is being deinitialized" +``` ## 类实例之间的循环强引用 @@ -96,19 +104,23 @@ ARC 会在第三个,也即最后一个强引用被断开的时候,销毁`Per 下面展示了一个不经意产生循环强引用的例子。例子定义了两个类:`Person`和`Apartment`,用来建模公寓和它其中的居民: - class Person { - let name: String - init(name: String) { self.name = name } - var apartment: Apartment? - deinit { println("\(name) is being deinitialized") } - } +```swift +class Person { + let name: String + init(name: String) { self.name = name } + var apartment: Apartment? + deinit { println("\(name) is being deinitialized") } +} +``` - class Apartment { - let number: Int - init(number: Int) { self.number = number } - var tenant: Person? - deinit { println("Apartment #\(number) is being deinitialized") } - } +```swift +class Apartment { + let number: Int + init(number: Int) { self.number = number } + var tenant: Person? + deinit { println("Apartment #\(number) is being deinitialized") } +} +``` 每一个`Person`实例有一个类型为`String`,名字为`name`的属性,并有一个可选的初始化为`nil`的`apartment`属性。`apartment`属性是可选的,因为一个人并不总是拥有公寓。 @@ -118,13 +130,17 @@ ARC 会在第三个,也即最后一个强引用被断开的时候,销毁`Per 接下来的代码片段定义了两个可选类型的变量`john`和`number73`,并分别被设定为下面的`Apartment`和`Person`的实例。这两个变量都被初始化为`nil`,并为可选的: - var john: Person? - var number73: Apartment? +```swift +var john: Person? +var number73: Apartment? +``` 现在你可以创建特定的`Person`和`Apartment`实例并将类实例赋值给`john`和`number73`变量: - john = Person(name: "John Appleseed") - number73 = Apartment(number: 73) +```swift +john = Person(name: "John Appleseed") +number73 = Apartment(number: 73) +``` 在两个实例被创建和赋值后,下图表现了强引用的关系。变量`john`现在有一个指向`Person`实例的强引用,而变量`number73`有一个指向`Apartment`实例的强引用: @@ -132,8 +148,10 @@ ARC 会在第三个,也即最后一个强引用被断开的时候,销毁`Per 现在你能够将这两个实例关联在一起,这样人就能有公寓住了,而公寓也有了房客。注意感叹号是用来展开和访问可选变量`john`和`number73`中的实例,这样实例的属性才能被赋值: - john!.apartment = number73 - number73!.tenant = john +```swift +john!.apartment = number73 +number73!.tenant = john +``` 在将两个实例联系在一起之后,强引用的关系如图所示: @@ -141,8 +159,10 @@ ARC 会在第三个,也即最后一个强引用被断开的时候,销毁`Per 不幸的是,将这两个实例关联在一起之后,一个循环强引用被创建了。`Person`实例现在有了一个指向`Apartment`实例的强引用,而`Apartment`实例也有了一个指向`Person`实例的强引用。因此,当你断开`john`和`number73`变量所持有的强引用时,引用计数并不会降为 0,实例也不会被 ARC 销毁: - john = nil - number73 = nil +```swift +john = nil +number73 = nil +``` 注意,当你把这两个变量设为`nil`时,没有任何一个析构函数被调用。强引用循环阻止了`Person`和`Apartment`类实例的销毁,并在你的应用程序中造成了内存泄漏。 @@ -161,15 +181,14 @@ Swift 提供了两种办法用来解决你在使用类的属性时所遇到的 对于生命周期中会变为`nil`的实例使用弱引用。相反的,对于初始化赋值后再也不会被赋值为`nil`的实例,使用无主引用。 - ### 弱引用 弱引用不会牢牢保持住引用的实例,并且不会阻止 ARC 销毁被引用的实例。这种行为阻止了引用变为循环强引用。声明属性或者变量时,在前面加上`weak`关键字表明这是一个弱引用。 在实例的生命周期中,如果某些时候引用没有值,那么弱引用可以阻止循环强引用。如果引用总是有值,则可以使用无主引用,在[无主引用](#2)中有描述。在上面`Apartment`的例子中,一个公寓的生命周期中,有时是没有“居民”的,因此适合使用弱引用来解决循环强引用。 -> 注意: -> 弱引用必须被声明为变量,表明其值能在运行时被修改。弱引用不能被声明为常量。 +> 注意: +> 弱引用必须被声明为变量,表明其值能在运行时被修改。弱引用不能被声明为常量。 因为弱引用可以没有值,你必须将每一个弱引用声明为可选类型。可选类型是在 Swift 语言中推荐的用来表示可能没有值的类型。 @@ -177,30 +196,36 @@ Swift 提供了两种办法用来解决你在使用类的属性时所遇到的 下面的例子跟上面`Person`和`Apartment`的例子一致,但是有一个重要的区别。这一次,`Apartment`的`tenant`属性被声明为弱引用: - class Person { - let name: String - init(name: String) { self.name = name } - var apartment: Apartment? - deinit { println("\(name) is being deinitialized") } - } +```swift +class Person { + let name: String + init(name: String) { self.name = name } + var apartment: Apartment? + deinit { println("\(name) is being deinitialized") } +} +``` - class Apartment { - let number: Int - init(number: Int) { self.number = number } - weak var tenant: Person? - deinit { println("Apartment #\(number) is being deinitialized") } - } +```swift +class Apartment { + let number: Int + init(number: Int) { self.number = number } + weak var tenant: Person? + deinit { println("Apartment #\(number) is being deinitialized") } +} +``` 然后跟之前一样,建立两个变量(john和number73)之间的强引用,并关联两个实例: - var john: Person? - var number73: Apartment? +```swift +var john: Person? +var number73: Apartment? - john = Person(name: "John Appleseed") - number73 = Apartment(number: 73) +john = Person(name: "John Appleseed") +number73 = Apartment(number: 73) - john!.apartment = number73 - number73!.tenant = john +john!.apartment = number73 +number73!.tenant = john +``` 现在,两个关联在一起的实例的引用关系如下图所示: @@ -212,8 +237,10 @@ Swift 提供了两种办法用来解决你在使用类的属性时所遇到的 由于再也没有指向`Person`实例的强引用,该实例会被销毁: - john = nil - // prints "John Appleseed is being deinitialized" +```swift +john = nil +// prints "John Appleseed is being deinitialized" +``` 唯一剩下的指向`Apartment`实例的强引用来自于变量`number73`。如果你断开这个强引用,再也没有指向`Apartment`实例的强引用了: @@ -221,8 +248,10 @@ Swift 提供了两种办法用来解决你在使用类的属性时所遇到的 由于再也没有指向`Apartment`实例的强引用,该实例也会被销毁: - number73 = nil - // prints "Apartment #73 is being deinitialized" +```swift +number73 = nil +// prints "Apartment #73 is being deinitialized" +``` 上面的两段代码展示了变量`john`和`number73`在被赋值为`nil`后,`Person`实例和`Apartment`实例的析构函数都打印出“销毁”的信息。这证明了引用循环被打破了。 @@ -233,10 +262,9 @@ Swift 提供了两种办法用来解决你在使用类的属性时所遇到的 由于无主引用是非可选类型,你不需要在使用它的时候将它展开。无主引用总是可以被直接访问。不过 ARC 无法在实例被销毁后将无主引用设为`nil`,因为非可选类型的变量不允许被赋值为`nil`。 -> 注意: ->如果你试图在实例被销毁后,访问该实例的无主引用,会触发运行时错误。使用无主引用,你必须确保引用始终指向一个未销毁的实例。 - -> 还需要注意的是如果你试图访问实例已经被销毁的无主引用,程序会直接崩溃,而不会发生无法预期的行为。所以你应当避免这样的事情发生。 +> 注意: +>如果你试图在实例被销毁后,访问该实例的无主引用,会触发运行时错误。使用无主引用,你必须确保引用始终指向一个未销毁的实例。 +> 还需要注意的是如果你试图访问实例已经被销毁的无主引用,程序会直接崩溃,而不会发生无法预期的行为。所以你应当避免这样的事情发生。 下面的例子定义了两个类,`Customer`和`CreditCard`,模拟了银行客户和客户的信用卡。这两个类中,每一个都将另外一个类的实例作为自身的属性。这种关系会潜在的创造循环强引用。 @@ -246,33 +274,41 @@ Swift 提供了两种办法用来解决你在使用类的属性时所遇到的 由于信用卡总是关联着一个客户,因此将`customer`属性定义为无主引用,用以避免循环强引用: - class Customer { - let name: String - var card: CreditCard? - init(name: String) { - self.name = name - } - deinit { println("\(name) is being deinitialized") } +```swift +class Customer { + let name: String + var card: CreditCard? + init(name: String) { + self.name = name } + deinit { println("\(name) is being deinitialized") } +} +``` - class CreditCard { - let number: Int - unowned let customer: Customer - init(number: Int, customer: Customer) { - self.number = number - self.customer = customer - } - deinit { println("Card #\(number) is being deinitialized") } +```swift +class CreditCard { + let number: Int + unowned let customer: Customer + init(number: Int, customer: Customer) { + self.number = number + self.customer = customer } + deinit { println("Card #\(number) is being deinitialized") } +} +``` 下面的代码片段定义了一个叫`john`的可选类型`Customer`变量,用来保存某个特定客户的引用。由于是可选类型,所以变量被初始化为`nil`。 - var john: Customer? +```swift +var john: Customer? +``` 现在你可以创建`Customer`类的实例,用它初始化`CreditCard`实例,并将新创建的`CreditCard`实例赋值为客户的`card`属性。 - john = Customer(name: "John Appleseed") - john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!) +```swift +john = Customer(name: "John Appleseed") +john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!) +``` 在你关联两个实例后,他们的引用关系如下图所示: @@ -286,13 +322,14 @@ Swift 提供了两种办法用来解决你在使用类的属性时所遇到的 由于再也没有指向`Customer`实例的强引用,该实例被销毁了。其后,再也没有指向`CreditCard`实例的强引用,该实例也随之被销毁了: - john = nil - // prints "John Appleseed is being deinitialized" - // prints "Card #1234567890123456 is being deinitialized" +```swift +john = nil +// prints "John Appleseed is being deinitialized" +// prints "Card #1234567890123456 is being deinitialized" +``` 最后的代码展示了在`john`变量被设为`nil`后`Customer`实例和`CreditCard`实例的构造函数都打印出了“销毁”的信息。 - ###无主引用以及隐式解析可选属性 上面弱引用和无主引用的例子涵盖了两种常用的需要打破循环强引用的场景。 @@ -307,23 +344,27 @@ Swift 提供了两种办法用来解决你在使用类的属性时所遇到的 下面的例子定义了两个类,`Country`和`City`,每个类将另外一个类的实例保存为属性。在这个模型中,每个国家必须有首都,而每一个城市必须属于一个国家。为了实现这种关系,`Country`类拥有一个`capitalCity`属性,而`City`类有一个`country`属性: - class Country { - let name: String - let capitalCity: City! - init(name: String, capitalName: String) { - self.name = name - self.capitalCity = City(name: capitalName, country: self) - } +```swift +class Country { + let name: String + let capitalCity: City! + init(name: String, capitalName: String) { + self.name = name + self.capitalCity = City(name: capitalName, country: self) } +} +``` - class City { - let name: String - unowned let country: Country - init(name: String, country: Country) { - self.name = name - self.country = country - } +```swift +class City { + let name: String + unowned let country: Country + init(name: String, country: Country) { + self.name = name + self.country = country } +} +``` 为了建立两个类的依赖关系,`City`的构造函数有一个`Country`实例的参数,并且将实例保存为`country`属性。 @@ -335,9 +376,11 @@ Swift 提供了两种办法用来解决你在使用类的属性时所遇到的 以上的意义在于你可以通过一条语句同时创建`Country`和`City`的实例,而不产生循环强引用,并且`capitalCity`的属性能被直接访问,而不需要通过感叹号来展开它的可选值: - var country = Country(name: "Canada", capitalName: "Ottawa") - println("\(country.name)'s capital city is called \(country.capitalCity.name)") - // prints "Canada's capital city is called Ottawa" +```swift +var country = Country(name: "Canada", capitalName: "Ottawa") +println("\(country.name)'s capital city is called \(country.capitalCity.name)") +// prints "Canada's capital city is called Ottawa" +``` 在上面的例子中,使用隐式解析可选值的意义在于满足了两个类构造函数的需求。`capitalCity`属性在初始化完成后,能像非可选值一样使用和存取同时还避免了循环强引用。 @@ -354,30 +397,32 @@ Swift 提供了一种优雅的方法来解决这个问题,称之为闭包占 下面的例子为你展示了当一个闭包引用了`self`后是如何产生一个循环强引用的。例子中定义了一个叫`HTMLElement`的类,用一种简单的模型表示 HTML 中的一个单独的元素: - class HTMLElement { +```swift +class HTMLElement { - let name: String - let text: String? + let name: String + let text: String? - @lazy var asHTML: () -> String = { - if let text = self.text { - return "<\(self.name)>\(text)" - } else { - return "<\(self.name) />" - } + @lazy var asHTML: () -> String = { + if let text = self.text { + return "<\(self.name)>\(text)" + } else { + return "<\(self.name) />" } - - init(name: String, text: String? = nil) { - self.name = name - self.text = text - } - - deinit { - println("\(name) is being deinitialized") - } - } + init(name: String, text: String? = nil) { + self.name = name + self.text = text + } + + deinit { + println("\(name) is being deinitialized") + } + +} +``` + `HTMLElement`类定义了一个`name`属性来表示这个元素的名称,例如代表段落的"p",或者代表换行的"br"。`HTMLElement`还定义了一个可选属性`text`,用来设置和展现 HTML 元素的文本。 除了上面的两个属性,`HTMLElement`还定义了一个`lazy`属性`asHTML`。这个属性引用了一个闭包,将`name`和`text`组合成 HTML 字符串片段。该属性是`() -> String`类型,或者可以理解为“一个没有参数,返回`String`的函数”。 @@ -386,20 +431,20 @@ Swift 提供了一种优雅的方法来解决这个问题,称之为闭包占 可以像实例方法那样去命名、使用`asHTML`属性。然而,由于`asHTML`是闭包而不是实例方法,如果你想改变特定元素的 HTML 处理的话,可以用自定义的闭包来取代默认值。 -> 注意: -> +> 注意: `asHTML`声明为`lazy`属性,因为只有当元素确实需要处理为HTML输出的字符串时,才需要使用`asHTML`。也就是说,在默认的闭包中可以使用`self`,因为只有当初始化完成以及`self`确实存在后,才能访问`lazy`属性。 `HTMLElement`类只提供一个构造函数,通过`name`和`text`(如果有的话)参数来初始化一个元素。该类也定义了一个析构函数,当`HTMLElement`实例被销毁时,打印一条消息。 下面的代码展示了如何用`HTMLElement`类创建实例并打印消息。 - var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") - println(paragraph!.asHTML()) - // prints"hello, world" +```swift +var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") +println(paragraph!.asHTML()) +// prints"hello, world" +``` ->注意: -> +>注意: 上面的`paragraph`变量定义为`可选HTMLElement`,因此我们可以赋值`nil`给它来演示循环强引用。 不幸的是,上面写的`HTMLElement`类产生了类实例和`asHTML`默认值的闭包之间的循环强引用。循环强引用如下图所示: @@ -408,13 +453,14 @@ Swift 提供了一种优雅的方法来解决这个问题,称之为闭包占 实例的`asHTML`属性持有闭包的强引用。但是,闭包在其闭包体内使用了`self`(引用了`self.name`和`self.text`),因此闭包捕获了`self`,这意味着闭包又反过来持有了`HTMLElement`实例的强引用。这样两个对象就产生了循环强引用。(更多关于闭包捕获值的信息,请参考[值捕获](07_Closures.html))。 ->注意: -> +>注意: 虽然闭包多次使用了`self`,它只捕获`HTMLElement`实例的一个强引用。 如果设置`paragraph`变量为`nil`,打破它持有的`HTMLElement`实例的强引用,`HTMLElement`实例和它的闭包都不会被销毁,也是因为循环强引用: - paragraph = nil +```swift +paragraph = nil +``` 注意`HTMLElementdeinitializer`中的消息并没有别打印,证明了`HTMLElement`实例并没有被销毁。 @@ -423,8 +469,7 @@ Swift 提供了一种优雅的方法来解决这个问题,称之为闭包占 在定义闭包时同时定义捕获列表作为闭包的一部分,通过这种方式可以解决闭包和类实例之间的循环强引用。捕获列表定义了闭包体内捕获一个或者多个引用类型的规则。跟解决两个类实例间的循环强引用一样,声明每个捕获的引用为弱引用或无主引用,而不是强引用。应当根据代码关系来决定使用弱引用还是无主引用。 ->注意: -> +>注意: Swift 有如下要求:只要在闭包内使用`self`的成员,就要用`self.someProperty`或者`self.someMethod`(而不只是`someProperty`或`someMethod`)。这提醒你可能会不小心就捕获了`self`。 ###定义捕获列表 @@ -433,17 +478,21 @@ Swift 有如下要求:只要在闭包内使用`self`的成员,就要用`self 捕获列表放置在闭包参数列表和返回类型之前: - @lazy var someClosure: (Int, String) -> String = { - [unowned self] (index: Int, stringToProcess: String) -> String in - // closure body goes here - } +```swift +@lazy var someClosure: (Int, String) -> String = { + [unowned self] (index: Int, stringToProcess: String) -> String in + // closure body goes here +} +``` 如果闭包没有指定参数列表或者返回类型,则可以通过上下文推断,那么可以捕获列表放在闭包开始的地方,跟着是关键字`in`: - @lazy var someClosure: () -> String = { - [unowned self] in - // closure body goes here - } +```swift +@lazy var someClosure: () -> String = { + [unowned self] in + // closure body goes here +} +``` ###弱引用和无主引用 @@ -451,44 +500,47 @@ Swift 有如下要求:只要在闭包内使用`self`的成员,就要用`self 相反的,当捕获引用有时可能会是`nil`时,将闭包内的捕获定义为弱引用。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为`nil`。这使我们可以在闭包内检查他们是否存在。 ->注意: -> +>注意: 如果捕获的引用绝对不会置为`nil`,应该用无主引用,而不是弱引用。 前面的`HTMLElement`例子中,无主引用是正确的解决循环强引用的方法。这样编写`HTMLElement`类来避免循环强引用: - class HTMLElement { +```swift +class HTMLElement { - let name: String - let text: String? + let name: String + let text: String? - @lazy var asHTML: () -> String = { - [unowned self] in - if let text = self.text { - return "<\(self.name)>\(text)" - } else { - return "<\(self.name) />" - } + @lazy var asHTML: () -> String = { + [unowned self] in + if let text = self.text { + return "<\(self.name)>\(text)" + } else { + return "<\(self.name) />" } - - init(name: String, text: String? = nil) { - self.name = name - self.text = text - } - - deinit { - println("\(name) is being deinitialized") - } - } + init(name: String, text: String? = nil) { + self.name = name + self.text = text + } + + deinit { + println("\(name) is being deinitialized") + } + +} +``` + 上面的`HTMLElement`实现和之前的实现一致,只是在`asHTML`闭包中多了一个捕获列表。这里,捕获列表是`[unowned self]`,表示“用无主引用而不是强引用来捕获`self`”。 和之前一样,我们可以创建并打印`HTMLElement`实例: - var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") - println(paragraph!.asHTML()) - // prints "

hello, world

" +```swift +var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") +println(paragraph!.asHTML()) +// prints "

hello, world

" +``` 使用捕获列表后引用关系如下图所示: @@ -496,5 +548,8 @@ Swift 有如下要求:只要在闭包内使用`self`的成员,就要用`self 这一次,闭包以无主引用的形式捕获`self`,并不会持有`HTMLElement`实例的强引用。如果将`paragraph`赋值为`nil`,`HTMLElement`实例将会被销毁,并能看到它的析构函数打印出的消息。 - paragraph = nil - // prints "p is being deinitialized" +```swift +paragraph = nil +// prints "p is being deinitialized" +``` + From 666da96748740ea4f3ee1f61e6ed6dd9bffca349 Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 19:10:30 +0800 Subject: [PATCH 02/14] fix 2.17 optional chainning --- source/chapter2/17_Optional_Chaining.md | 284 +++++++++++++----------- 1 file changed, 157 insertions(+), 127 deletions(-) diff --git a/source/chapter2/17_Optional_Chaining.md b/source/chapter2/17_Optional_Chaining.md index f10020dd..65156678 100644 --- a/source/chapter2/17_Optional_Chaining.md +++ b/source/chapter2/17_Optional_Chaining.md @@ -1,7 +1,5 @@ -> 翻译:Jasonbroker - -> 校对:numbbbbb - +> 翻译:Jasonbroker +> 校对:numbbbbb, stanzhai # Optional Chaining ----------------- @@ -18,7 +16,7 @@ 可选链(Optional Chaining)是一种可以请求和调用属性、方法及子脚本的过程,它的可选性体现于请求或调用的目标当前可能为空(`nil`)。如果可选的目标有值,那么调用就会成功;相反,如果选择的目标为空(`nil`),则这种调用将返回空(`nil`)。多次请求或调用可以被链接在一起形成一个链,如果任何一个节点为空(`nil`)将导致整个链失效。 -> 注意: +> 注意: Swift 的可选链和 Objective-C 中的消息为空有些相像,但是 Swift 可以使用在任意类型中,并且失败与否可以被检测到。 @@ -34,35 +32,42 @@ Swift 的可选链和 Objective-C 中的消息为空有些相像,但是 Swift 首先定义两个类`Person`和`Residence`。 - class Person { - var residence: Residence? - } +```swift +class Person { + var residence: Residence? +} - class Residence { - var numberOfRooms = 1 - } +class Residence { + var numberOfRooms = 1 +} +``` `Residence`具有一个`Int`类型的`numberOfRooms`,其值为 1。`Person`具有一个可选`residence`属性,它的类型是`Residence?`。 如果你创建一个新的`Person`实例,它的`residence`属性由于是被定义为可选型的,此属性将默认初始化为空: - let john = Person() +```swift +let john = Person() +``` 如果你想使用感叹号(`!`)强制解析获得这个人`residence`属性`numberOfRooms`属性值,将会引发运行时错误,因为这时没有可以供解析的`residence`值。 - let roomCount = john.residence!.numberOfRooms - //将导致运行时错误 +```swift +let roomCount = john.residence!.numberOfRooms +//将导致运行时错误 +``` 当`john.residence`不是`nil`时,会运行通过,且会将`roomCount` 设置为一个`int`类型的合理值。然而,如上所述,当`residence`为空时,这个代码将会导致运行时错误。 可选链提供了一种另一种获得`numberOfRooms`的方法。利用可选链,使用问号来代替原来`!`的位置: - if let roomCount = john.residence?.numberOfRooms { - println("John's residence has \(roomCount) room(s).") - } else { - println("Unable to retrieve the number of rooms.") - } - // 打印 "Unable to retrieve the number of rooms. - +```swift +if let roomCount = john.residence?.numberOfRooms { + println("John's residence has \(roomCount) room(s).") +} else { + println("Unable to retrieve the number of rooms.") +} +// 打印 "Unable to retrieve the number of rooms. +``` 这告诉 Swift 来链接可选`residence?`属性,如果`residence`存在则取回`numberOfRooms`的值。 @@ -72,16 +77,20 @@ Swift 的可选链和 Objective-C 中的消息为空有些相像,但是 Swift 你可以自己定义一个`Residence`实例给`john.residence`,这样它就不再为空了: - john.residence = Residence() +```swift +john.residence = Residence() +``` `john.residence` 现在有了实际存在的实例而不是nil了。如果你想使用和前面一样的可选链来获得`numberOfRoooms`,它将返回一个包含默认值 1 的`Int?`: - if let roomCount = john.residence?.numberOfRooms { - println("John's residence has \(roomCount) room(s).") - } else { - println("Unable to retrieve the number of rooms.") - } - // 打印 "John's residence has 1 room(s)"。 +```swift +if let roomCount = john.residence?.numberOfRooms { + println("John's residence has \(roomCount) room(s).") +} else { + println("Unable to retrieve the number of rooms.") +} +// 打印 "John's residence has 1 room(s)"。 +``` ##为可选链定义模型类 @@ -92,25 +101,29 @@ Swift 的可选链和 Objective-C 中的消息为空有些相像,但是 Swift `Person`类定义与之前相同。 - class Person { - var residence: Residence? - } +```swift +class Person { + var residence: Residence? +} +``` `Residence`类比之前复杂些。这次,它定义了一个变量 `rooms`,它被初始化为一个`Room[]`类型的空数组: - class Residence { - var rooms = Room[]() - var numberOfRooms: Int { - return rooms.count - } - subscript(i: Int) -> Room { - return rooms[i] - } - func printNumberOfRooms() { - println("The number of rooms is \(numberOfRooms)") - } - var address: Address? - } +```swift +class Residence { + var rooms = Room[]() + var numberOfRooms: Int { + return rooms.count + } + subscript(i: Int) -> Room { + return rooms[i] + } + func printNumberOfRooms() { + println("The number of rooms is \(numberOfRooms)") + } + var address: Address? +} +``` 因为`Residence`存储了一个`Room`实例的数组,它的`numberOfRooms`属性值不是一个固定的存储值,而是通过计算而来的。`numberOfRooms`属性值是由返回`rooms`数组的`count`属性值得到的。 @@ -121,28 +134,32 @@ Swift 的可选链和 Objective-C 中的消息为空有些相像,但是 Swift 最后,`Residence`定义了一个可选属性叫`address`(`address?`)。`Address`类的属性将在后面定义。 用于`rooms`数组的`Room`类是一个很简单的类,它只有一个`name`属性和一个设定`room`名的初始化器。 - class Room { - let name: String - init(name: String) { self.name = name } - } +```swift +class Room { + let name: String + init(name: String) { self.name = name } +} +``` 这个模型中的最终类叫做`Address`。它有三个类型是`String?`的可选属性。前面两个可选属性`buildingName`和 `buildingNumber`作为地址的一部分,是定义某个建筑物的两种方式。第三个属性`street`,用于命名地址的街道名: - class Address { - var buildingName: String? - var buildingNumber: String? - var street: String? - func buildingIdentifier() -> String? { - if buildingName { - return buildingName - } else if buildingNumber { - return buildingNumber - } else { - return nil - } - } - } +```swift +class Address { + var buildingName: String? + var buildingNumber: String? + var street: String? + func buildingIdentifier() -> String? { + if buildingName { + return buildingName + } else if buildingNumber { + return buildingNumber + } else { + return nil + } + } +} +``` `Address`类还提供了一个`buildingIdentifier`的方法,它的返回值类型为`String?`。这个方法检查`buildingName`和`buildingNumber`的属性,如果`buildingName`有值则将其返回,或者如果`buildingNumber`有值则将其返回,再或如果没有一个属性有值,返回空。 @@ -153,13 +170,15 @@ Swift 的可选链和 Objective-C 中的消息为空有些相像,但是 Swift 使用上述定义的类来创建一个人实例,并再次尝试后去它的`numberOfRooms`属性: - let john = Person() - if let roomCount = john.residence?.numberOfRooms { - println("John's residence has \(roomCount) room(s).") - } else { - println("Unable to retrieve the number of rooms.") - } - // 打印 "Unable to retrieve the number of rooms。 +```swift +let john = Person() +if let roomCount = john.residence?.numberOfRooms { + println("John's residence has \(roomCount) room(s).") +} else { + println("Unable to retrieve the number of rooms.") +} +// 打印 "Unable to retrieve the number of rooms。 +``` 由于`john.residence`是空,所以这个可选链和之前一样失败了,但是没有运行时错误。 @@ -170,53 +189,61 @@ Swift 的可选链和 Objective-C 中的消息为空有些相像,但是 Swift `Residence`的`printNumberOfRooms`方法会打印`numberOfRooms`的当前值。方法如下: - func printNumberOfRooms(){ - println(“The number of rooms is \(numberOfRooms)”) - } +```swift +func printNumberOfRooms(){ + println(“The number of rooms is \(numberOfRooms)”) +} +``` 这个方法没有返回值。但是,没有返回值类型的函数和方法有一个隐式的返回值类型`Void`(参见Function Without Return Values)。 如果你利用可选链调用此方法,这个方法的返回值类型将是`Void?`,而不是`Void`,因为当通过可选链调用方法时返回值总是可选类型(optional type)。即使这个方法本身没有定义返回值,你也可以使用`if`语句来检查是否能成功调用`printNumberOfRooms`方法:如果方法通过可选链调用成功,`printNumberOfRooms`的隐式返回值将会是`Void`,如果没有成功,将返回`nil`: - if john.residence?.printNumberOfRooms() { - println("It was possible to print the number of rooms.") - } else { - println("It was not possible to print the number of rooms.") - } - // 打印 "It was not possible to print the number of rooms."。 +```swift +if john.residence?.printNumberOfRooms() { + println("It was possible to print the number of rooms.") +} else { + println("It was not possible to print the number of rooms.") +} +// 打印 "It was not possible to print the number of rooms."。 +``` ##使用可选链调用子脚本 你可以使用可选链来尝试从子脚本获取值并检查子脚本的调用是否成功,然而,你不能通过可选链来设置子代码。 -> 注意: +> 注意: 当你使用可选链来获取子脚本的时候,你应该将问号放在子脚本括号的前面而不是后面。可选链的问号一般直接跟在表达语句的后面。 下面这个例子用在`Residence`类中定义的子脚本来获取`john.residence`数组中第一个房间的名字。因为`john.residence`现在是`nil`,子脚本的调用失败了。 - if let firstRoomName = john.residence?[0].name { - println("The first room name is \(firstRoomName).") - } else { - println("Unable to retrieve the first room name.") - } - // 打印 "Unable to retrieve the first room name."。 +```swift +if let firstRoomName = john.residence?[0].name { + println("The first room name is \(firstRoomName).") +} else { + println("Unable to retrieve the first room name.") +} +// 打印 "Unable to retrieve the first room name."。 +``` 在子代码调用中可选链的问号直接跟在`john.residence`的后面,在子脚本括号的前面,因为`john.residence`是可选链试图获得的可选值。 如果你创建一个`Residence`实例给`john.residence`,且在他的`rooms`数组中有一个或多个`Room`实例,那么你可以使用可选链通过`Residence`子脚本来获取在`rooms`数组中的实例了: - let johnsHouse = Residence() - johnsHouse.rooms += Room(name: "Living Room") - johnsHouse.rooms += Room(name: "Kitchen") - john.residence = johnsHouse +```swift +let johnsHouse = Residence() +johnsHouse.rooms += Room(name: "Living Room") +johnsHouse.rooms += Room(name: "Kitchen") +john.residence = johnsHouse - if let firstRoomName = john.residence?[0].name { - println("The first room name is \(firstRoomName).") - } else { - println("Unable to retrieve the first room name.") - } - // 打印 "The first room name is Living Room."。 +if let firstRoomName = john.residence?[0].name { + println("The first room name is \(firstRoomName).") +} else { + println("Unable to retrieve the first room name.") +} +// 打印 "The first room name is Living Room."。 +``` ##连接多层链接 @@ -234,12 +261,14 @@ Swift 的可选链和 Objective-C 中的消息为空有些相像,但是 Swift 下面的例子试图获取`john`的`residence`属性里的`address`的`street`属性。这里使用了两层可选链来联系`residence`和`address`属性,他们两者都是可选类型: - if let johnsStreet = john.residence?.address?.street { - println("John's street name is \(johnsStreet).") - } else { - println("Unable to retrieve the address.") - } - // 打印 "Unable to retrieve the address.”。 +```swift +if let johnsStreet = john.residence?.address?.street { + println("John's street name is \(johnsStreet).") +} else { + println("Unable to retrieve the address.") +} +// 打印 "Unable to retrieve the address.”。 +``` `john.residence`的值现在包含一个`Residence`实例,然而`john.residence.address`现在是`nil`,因此`john.residence?.address?.street`调用失败。 @@ -247,17 +276,21 @@ Swift 的可选链和 Objective-C 中的消息为空有些相像,但是 Swift 如果你为`Address`设定一个实例来作为`john.residence.address`的值,并为`address`的`street`属性设定一个实际值,你可以通过多层可选链来得到这个属性值。 - let johnsAddress = Address() - johnsAddress.buildingName = "The Larches" - johnsAddress.street = "Laurel Street" - john.residence!.address = johnsAddress +```swift +let johnsAddress = Address() +johnsAddress.buildingName = "The Larches" +johnsAddress.street = "Laurel Street" +john.residence!.address = johnsAddress +``` - if let johnsStreet = john.residence?.address?.street { - println("John's street name is \(johnsStreet).") - } else { - println("Unable to retrieve the address.") - } - // 打印 "John's street name is Laurel Street."。 +```swift +if let johnsStreet = john.residence?.address?.street { + println("John's street name is \(johnsStreet).") +} else { + println("Unable to retrieve the address.") +} +// 打印 "John's street name is Laurel Street."。 +``` 值得注意的是,“`!`”符号在给`john.residence.address`分配`address`实例时的使用。`john.residence`属性是一个可选类型,因此你需要在它获取`address`属性之前使用`!`解析以获得它的实际值。 @@ -268,24 +301,21 @@ Swift 的可选链和 Objective-C 中的消息为空有些相像,但是 Swift 下面的例子通过可选链调用了`Address`类中的`buildingIdentifier` 方法。这个方法的返回值类型是`String?`。如上所述,这个方法在可选链调用后最终的返回值类型依然是`String?`: - if let buildingIdentifier = john.residence?.address?.buildingIdentifier() { - println("John's building identifier is \(buildingIdentifier).") - } - // 打印 "John's building identifier is The Larches."。 +```swift +if let buildingIdentifier = john.residence?.address?.buildingIdentifier() { + println("John's building identifier is \(buildingIdentifier).") +} +// 打印 "John's building identifier is The Larches."。 +``` 如果你还想进一步对方法返回值执行可选链,将可选链问号符放在方法括号的后面: - if let upper = john.residence?.address?.buildingIdentifier()?.uppercaseString { - println("John's uppercase building identifier is \(upper).") - } - // 打印 "John's uppercase building identifier is THE LARCHES."。 +```swift +if let upper = john.residence?.address?.buildingIdentifier()?.uppercaseString { + println("John's uppercase building identifier is \(upper).") +} +// 打印 "John's uppercase building identifier is THE LARCHES."。 +``` -> 注意: +> 注意: 在上面的例子中,你将可选链问号符放在括号后面是因为你想要链接的可选值是`buildingIdentifier`方法的返回值,不是`buildingIdentifier`方法本身。 - - - - - - - From fcb99de0bedb7b5fabe4725156ca2f0dfa537494 Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 19:26:45 +0800 Subject: [PATCH 03/14] fix 2.18 type casting --- source/chapter2/18_Type_Casting.md | 320 +++++++++++++++-------------- 1 file changed, 167 insertions(+), 153 deletions(-) diff --git a/source/chapter2/18_Type_Casting.md b/source/chapter2/18_Type_Casting.md index ae5750e0..4f4f2477 100644 --- a/source/chapter2/18_Type_Casting.md +++ b/source/chapter2/18_Type_Casting.md @@ -1,6 +1,5 @@ -> 翻译:xiehurricane - -> 校对:happyming +> 翻译:xiehurricane +> 校对:happyming # 类型转换(Type Casting) ----------------- @@ -13,227 +12,242 @@ - [`Any`和`AnyObject`的类型转换](#type_casting_for_any_and_anyobject) - _类型检查_是一种检查类实例的方式,并且或者也是让实例作为它的父类或者子类的一种方式。 +_类型检查_是一种检查类实例的方式,并且或者也是让实例作为它的父类或者子类的一种方式。 - 类型检查在 Swift 中使用`is` 和 `as`操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。 +类型检查在 Swift 中使用`is` 和 `as`操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。 - 你也可以用来检查一个类是否实现了某个协议,就像在 [Checking for Protocol Conformance](Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_363)部分讲述的一样。 +你也可以用来检查一个类是否实现了某个协议,就像在 [Checking for Protocol Conformance](Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_363)部分讲述的一样。 ## 定义一个类层次作为例子 - 你可以将它用在类和子类的层次结构上,检查特定类实例的类型并且转换这个类实例的类型成为这个层次结构中的其他类型。这下面的三个代码段定义了一个类层次和一个包含了几个这些类实例的数组,作为类型检查的例子。 +你可以将它用在类和子类的层次结构上,检查特定类实例的类型并且转换这个类实例的类型成为这个层次结构中的其他类型。这下面的三个代码段定义了一个类层次和一个包含了几个这些类实例的数组,作为类型检查的例子。 - 第一个代码片段定义了一个新的基础类`MediaItem`。这个类为任何出现在数字媒体库的媒体项提供基础功能。特别的,它声明了一个 `String` 类型的 `name` 属性,和一个`init name`初始化器。(它假定所有的媒体项都有个名称。) +第一个代码片段定义了一个新的基础类`MediaItem`。这个类为任何出现在数字媒体库的媒体项提供基础功能。特别的,它声明了一个 `String` 类型的 `name` 属性,和一个`init name`初始化器。(它假定所有的媒体项都有个名称。) - class MediaItem { - var name: String - init(name: String) { - self.name = name - } +```swift +class MediaItem { + var name: String + init(name: String) { + self.name = name } +} +``` - 下一个代码段定义了 `MediaItem` 的两个子类。第一个子类`Movie`,在父类(或者说基类)的基础上增加了一个 `director`(导演) 属性,和相应的初始化器。第二个类在父类的基础上增加了一个 `artist`(艺术家) 属性,和相应的初始化器: +下一个代码段定义了 `MediaItem` 的两个子类。第一个子类`Movie`,在父类(或者说基类)的基础上增加了一个 `director`(导演) 属性,和相应的初始化器。第二个类在父类的基础上增加了一个 `artist`(艺术家) 属性,和相应的初始化器: - class Movie: MediaItem { - var director: String - init(name: String, director: String) { - self.director = director - super.init(name: name) - } +```swift +class Movie: MediaItem { + var director: String + init(name: String, director: String) { + self.director = director + super.init(name: name) } +} - class Song: MediaItem { - var artist: String - init(name: String, artist: String) { - self.artist = artist - super.init(name: name) - } +class Song: MediaItem { + var artist: String + init(name: String, artist: String) { + self.artist = artist + super.init(name: name) } +} +``` - 最后一个代码段创建了一个数组常量 `library` - ,包含两个`Movie`实例和三个`Song`实例。`library`的类型是在它被初始化时根据它数组中所包含的内容推断来的。Swift 的类型检测器能够演绎出`Movie` 和 `Song` 有共同的父类 `MediaItem` ,所以它推断出 `MediaItem[]` 类作为 `library` 的类型。 +最后一个代码段创建了一个数组常量 `library`,包含两个`Movie`实例和三个`Song`实例。`library`的类型是在它被初始化时根据它数组中所包含的内容推断来的。Swift 的类型检测器能够演绎出`Movie` 和 `Song` 有共同的父类 `MediaItem` ,所以它推断出 `MediaItem[]` 类作为 `library` 的类型。 - let library = [ - Movie(name: "Casablanca", director: "Michael Curtiz"), - Song(name: "Blue Suede Shoes", artist: "Elvis Presley"), - Movie(name: "Citizen Kane", director: "Orson Welles"), - Song(name: "The One And Only", artist: "Chesney Hawkes"), - Song(name: "Never Gonna Give You Up", artist: "Rick Astley") - ] - // the type of "library" is inferred to be MediaItem[] +```swift +let library = [ + Movie(name: "Casablanca", director: "Michael Curtiz"), + Song(name: "Blue Suede Shoes", artist: "Elvis Presley"), + Movie(name: "Citizen Kane", director: "Orson Welles"), + Song(name: "The One And Only", artist: "Chesney Hawkes"), + Song(name: "Never Gonna Give You Up", artist: "Rick Astley") +] +// the type of "library" is inferred to be MediaItem[] +``` - 在幕后`library` 里存储的媒体项依然是 `Movie` 和 `Song` 类型的,但是,若你迭代它,取出的实例会是 `MediaItem` 类型的,而不是 `Movie` 和 `Song` 类型的。为了让它们作为它们本来的类型工作,你需要检查它们的类型或者向下转换它们的类型到其它类型,就像下面描述的一样。 +在幕后`library` 里存储的媒体项依然是 `Movie` 和 `Song` 类型的,但是,若你迭代它,取出的实例会是 `MediaItem` 类型的,而不是 `Movie` 和 `Song` 类型的。为了让它们作为它们本来的类型工作,你需要检查它们的类型或者向下转换它们的类型到其它类型,就像下面描述的一样。 ## 检查类型 - 用类型检查操作符(`is`)来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 `true` ,否则返回 `false` 。 +用类型检查操作符(`is`)来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 `true` ,否则返回 `false` 。 - 下面的例子定义了两个变量,`movieCount` 和 `songCount`,用来计算数组`library` 中 `Movie` 和 `Song` 类型的实例数量。 +下面的例子定义了两个变量,`movieCount` 和 `songCount`,用来计算数组`library` 中 `Movie` 和 `Song` 类型的实例数量。 - var movieCount = 0 - var songCount = 0 +```swift +var movieCount = 0 +var songCount = 0 - for item in library { - if item is Movie { - ++movieCount - } else if item is Song { - ++songCount - } +for item in library { + if item is Movie { + ++movieCount + } else if item is Song { + ++songCount } +} - println("Media library contains \(movieCount) movies and \(songCount) songs") - // prints "Media library contains 2 movies and 3 songs" +println("Media library contains \(movieCount) movies and \(songCount) songs") +// prints "Media library contains 2 movies and 3 songs" +``` - 示例迭代了数组 `library` 中的所有项。每一次, `for`-`in` 循环设置 - `item` 为数组中的下一个 `MediaItem`。 +示例迭代了数组 `library` 中的所有项。每一次, `for`-`in` 循环设置 +`item` 为数组中的下一个 `MediaItem`。 - 若当前 `MediaItem` 是一个 `Movie` 类型的实例, `item is Movie` 返回 - `true`,相反返回 `false`。同样的,`item is - Song`检查item是否为`Song`类型的实例。在循环结束后,`movieCount` 和 `songCount`的值就是被找到属于各自的类型的实例数量。 +若当前 `MediaItem` 是一个 `Movie` 类型的实例, `item is Movie` 返回 +`true`,相反返回 `false`。同样的,`item is +Song`检查item是否为`Song`类型的实例。在循环结束后,`movieCount` 和 `songCount`的值就是被找到属于各自的类型的实例数量。 ## 向下转型(Downcasting) - 某类型的一个常量或变量可能在幕后实际上属于一个子类。你可以相信,上面就是这种情况。你可以尝试向下转到它的子类型,用类型转换操作符(`as`) +某类型的一个常量或变量可能在幕后实际上属于一个子类。你可以相信,上面就是这种情况。你可以尝试向下转到它的子类型,用类型转换操作符(`as`) - 因为向下转型可能会失败,类型转型操作符带有两种不同形式。可选形式( optional form) `as?` 返回一个你试图下转成的类型的可选值(optional value)。强制形式 `as` 把试图向下转型和强制解包(force-unwraps)结果作为一个混合动作。 +因为向下转型可能会失败,类型转型操作符带有两种不同形式。可选形式( optional form) `as?` 返回一个你试图下转成的类型的可选值(optional value)。强制形式 `as` 把试图向下转型和强制解包(force-unwraps)结果作为一个混合动作。 - 当你不确定向下转型可以成功时,用类型转换的可选形式(`as?`)。可选形式的类型转换总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 `nil` 。这使你能够检查向下转型是否成功。 +当你不确定向下转型可以成功时,用类型转换的可选形式(`as?`)。可选形式的类型转换总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 `nil` 。这使你能够检查向下转型是否成功。 - 只有你可以确定向下转型一定会成功时,才使用强制形式。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。 +只有你可以确定向下转型一定会成功时,才使用强制形式。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。 - 下面的例子,迭代了`library`里的每一个 `MediaItem` ,并打印出适当的描述。要这样做,`item`需要真正作为`Movie` 或 `Song`的类型来使用。不仅仅是作为 `MediaItem`。为了能够使用`Movie` 或 `Song`的 `director` 或 `artist`属性,这是必要的。 +下面的例子,迭代了`library`里的每一个 `MediaItem` ,并打印出适当的描述。要这样做,`item`需要真正作为`Movie` 或 `Song`的类型来使用。不仅仅是作为 `MediaItem`。为了能够使用`Movie` 或 `Song`的 `director` 或 `artist`属性,这是必要的。 - 在这个示例中,数组中的每一个`item`可能是 `Movie` 或 `Song`。 事前你不知道每个`item`的真实类型,所以这里使用可选形式的类型转换 (`as?`)去检查循环里的每次下转。 +在这个示例中,数组中的每一个`item`可能是 `Movie` 或 `Song`。 事前你不知道每个`item`的真实类型,所以这里使用可选形式的类型转换 (`as?`)去检查循环里的每次下转。 - for item in library { - if let movie = item as? Movie { - println("Movie: '\(movie.name)', dir. \(movie.director)") - } else if let song = item as? Song { - println("Song: '\(song.name)', by \(song.artist)") - } +```swift +for item in library { + if let movie = item as? Movie { + println("Movie: '\(movie.name)', dir. \(movie.director)") + } else if let song = item as? Song { + println("Song: '\(song.name)', by \(song.artist)") } +} - // Movie: 'Casablanca', dir. Michael Curtiz - // Song: 'Blue Suede Shoes', by Elvis Presley - // Movie: 'Citizen Kane', dir. Orson Welles - // Song: 'The One And Only', by Chesney Hawkes - // Song: 'Never Gonna Give You Up', by Rick Astley +// Movie: 'Casablanca', dir. Michael Curtiz +// Song: 'Blue Suede Shoes', by Elvis Presley +// Movie: 'Citizen Kane', dir. Orson Welles +// Song: 'The One And Only', by Chesney Hawkes +// Song: 'Never Gonna Give You Up', by Rick Astley +``` - 示例首先试图将 `item` 下转为 `Movie`。因为 `item` 是一个 `MediaItem` - 类型的实例,它可能是一个`Movie`;同样,它可能是一个 `Song`,或者仅仅是基类 - `MediaItem`。因为不确定,`as?`形式在试图下转时将返还一个可选值。 `item as Movie` 的返回值是`Movie?`类型或 “optional `Movie`”。 +示例首先试图将 `item` 下转为 `Movie`。因为 `item` 是一个 `MediaItem` +类型的实例,它可能是一个`Movie`;同样,它可能是一个 `Song`,或者仅仅是基类 +`MediaItem`。因为不确定,`as?`形式在试图下转时将返还一个可选值。 `item as Movie` 的返回值是`Movie?`类型或 “optional `Movie`”。 - 当向下转型为 `Movie` 应用在两个 `Song` - 实例时将会失败。为了处理这种情况,上面的例子使用了可选绑定(optional binding)来检查可选 `Movie`真的包含一个值(这个是为了判断下转是否成功。)可选绑定是这样写的“`if let movie = item as? Movie`”,可以这样解读: +当向下转型为 `Movie` 应用在两个 `Song` +实例时将会失败。为了处理这种情况,上面的例子使用了可选绑定(optional binding)来检查可选 `Movie`真的包含一个值(这个是为了判断下转是否成功。)可选绑定是这样写的“`if let movie = item as? Movie`”,可以这样解读: - “尝试将 `item` 转为 `Movie`类型。若成功,设置一个新的临时常量 `movie` 来存储返回的可选`Movie`” +“尝试将 `item` 转为 `Movie`类型。若成功,设置一个新的临时常量 `movie` 来存储返回的可选`Movie`” - 若向下转型成功,然后`movie`的属性将用于打印一个`Movie`实例的描述,包括它的导演的名字`director`。当`Song`被找到时,一个相近的原理被用来检测 `Song` 实例和打印它的描述。 +若向下转型成功,然后`movie`的属性将用于打印一个`Movie`实例的描述,包括它的导演的名字`director`。当`Song`被找到时,一个相近的原理被用来检测 `Song` 实例和打印它的描述。 -> 注意: -> +> 注意: 转换没有真的改变实例或它的值。潜在的根本的实例保持不变;只是简单地把它作为它被转换成的类来使用。 ## `Any`和`AnyObject`的类型转换 - Swift为不确定类型提供了两种特殊类型别名: +Swift为不确定类型提供了两种特殊类型别名: - * `AnyObject`可以代表任何class类型的实例。 +* `AnyObject`可以代表任何class类型的实例。 +* `Any`可以表示任何类型,除了方法类型(function types)。 - * `Any`可以表示任何类型,除了方法类型(function types)。 - -> 注意: -> +> 注意: 只有当你明确的需要它的行为和功能时才使用`Any`和`AnyObject`。在你的代码里使用你期望的明确的类型总是更好的。 ### `AnyObject`类型 - 当需要在工作中使用 Cocoa - APIs,它一般接收一个`AnyObject[]`类型的数组,或者说“一个任何对象类型的数组”。这是因为 Objective-C 没有明确的类型化数组。但是,你常常可以确定包含在仅从你知道的 API 信息提供的这样一个数组中的对象的类型。 +当需要在工作中使用 Cocoa +APIs,它一般接收一个`AnyObject[]`类型的数组,或者说“一个任何对象类型的数组”。这是因为 Objective-C 没有明确的类型化数组。但是,你常常可以确定包含在仅从你知道的 API 信息提供的这样一个数组中的对象的类型。 - 在这些情况下,你可以使用强制形式的类型转换(`as`)来下转在数组中的每一项到比 `AnyObject` 更明确的类型,不需要可选解析(optional unwrapping)。 +在这些情况下,你可以使用强制形式的类型转换(`as`)来下转在数组中的每一项到比 `AnyObject` 更明确的类型,不需要可选解析(optional unwrapping)。 - 下面的示例定义了一个 `AnyObject[]` 类型的数组并填入三个`Movie`类型的实例: +下面的示例定义了一个 `AnyObject[]` 类型的数组并填入三个`Movie`类型的实例: - let someObjects: AnyObject[] = [ - Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"), - Movie(name: "Moon", director: "Duncan Jones"), - Movie(name: "Alien", director: "Ridley Scott") - ] +```swift +let someObjects: AnyObject[] = [ + Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"), + Movie(name: "Moon", director: "Duncan Jones"), + Movie(name: "Alien", director: "Ridley Scott") +] +``` - 因为知道这个数组只包含 `Movie` 实例,你可以直接用(`as`)下转并解包到不可选的`Movie`类型(ps:其实就是我们常用的正常类型,这里是为了和可选类型相对比)。 +因为知道这个数组只包含 `Movie` 实例,你可以直接用(`as`)下转并解包到不可选的`Movie`类型(ps:其实就是我们常用的正常类型,这里是为了和可选类型相对比)。 - for object in someObjects { - let movie = object as Movie - println("Movie: '\(movie.name)', dir. \(movie.director)") - } - // Movie: '2001: A Space Odyssey', dir. Stanley Kubrick - // Movie: 'Moon', dir. Duncan Jones - // Movie: 'Alien', dir. Ridley Scott +```swift +for object in someObjects { + let movie = object as Movie + println("Movie: '\(movie.name)', dir. \(movie.director)") +} +// Movie: '2001: A Space Odyssey', dir. Stanley Kubrick +// Movie: 'Moon', dir. Duncan Jones +// Movie: 'Alien', dir. Ridley Scott +``` - 为了变为一个更短的形式,下转`someObjects`数组为`Movie[]`类型来代替下转每一项方式。 +为了变为一个更短的形式,下转`someObjects`数组为`Movie[]`类型来代替下转每一项方式。 - for movie in someObjects as Movie[] { - println("Movie: '\(movie.name)', dir. \(movie.director)") - } - // Movie: '2001: A Space Odyssey', dir. Stanley Kubrick - // Movie: 'Moon', dir. Duncan Jones - // Movie: 'Alien', dir. Ridley Scott +```swift +for movie in someObjects as Movie[] { + println("Movie: '\(movie.name)', dir. \(movie.director)") +} +// Movie: '2001: A Space Odyssey', dir. Stanley Kubrick +// Movie: 'Moon', dir. Duncan Jones +// Movie: 'Alien', dir. Ridley Scott +``` ### `Any`类型 - 这里有个示例,使用 `Any` 类型来和混合的不同类型一起工作,包括非`class`类型。它创建了一个可以存储`Any`类型的数组 `things`。 +这里有个示例,使用 `Any` 类型来和混合的不同类型一起工作,包括非`class`类型。它创建了一个可以存储`Any`类型的数组 `things`。 - var things = Any[]() +```swift +var things = Any[]() - things.append(0) - things.append(0.0) - things.append(42) - things.append(3.14159) - things.append("hello") - things.append((3.0, 5.0)) - things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman")) +things.append(0) +things.append(0.0) +things.append(42) +things.append(3.14159) +things.append("hello") +things.append((3.0, 5.0)) +things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman")) +``` - `things` 数组包含两个 `Int` 值,2个 `Double` 值,1个 `String` 值,一个元组 `(Double, Double)` ,Ivan Reitman 导演的电影“Ghostbusters”。 +`things` 数组包含两个 `Int` 值,2个 `Double` 值,1个 `String` 值,一个元组 `(Double, Double)` ,Ivan Reitman 导演的电影“Ghostbusters”。 - 你可以在 `switch` `cases`里用`is` 和 `as` 操作符来发觉只知道是 `Any` 或 `AnyObject`的常量或变量的类型。 下面的示例迭代 `things`数组中的每一项的并用`switch`语句查找每一项的类型。这几种`switch`语句的情形绑定它们匹配的值到一个规定类型的常量,让它们可以打印它们的值: +你可以在 `switch` `cases`里用`is` 和 `as` 操作符来发觉只知道是 `Any` 或 `AnyObject`的常量或变量的类型。 下面的示例迭代 `things`数组中的每一项的并用`switch`语句查找每一项的类型。这几种`switch`语句的情形绑定它们匹配的值到一个规定类型的常量,让它们可以打印它们的值: - for thing in things { - switch thing { - case 0 as Int: - println("zero as an Int") - case 0 as Double: - println("zero as a Double") - case let someInt as Int: - println("an integer value of \(someInt)") - case let someDouble as Double where someDouble > 0: - println("a positive double value of \(someDouble)") - case is Double: - println("some other double value that I don't want to print") - case let someString as String: - println("a string value of \"\(someString)\"") - case let (x, y) as (Double, Double): - println("an (x, y) point at \(x), \(y)") - case let movie as Movie: - println("a movie called '\(movie.name)', dir. \(movie.director)") - default: - println("something else") - } +```swift +for thing in things { + switch thing { + case 0 as Int: + println("zero as an Int") + case 0 as Double: + println("zero as a Double") + case let someInt as Int: + println("an integer value of \(someInt)") + case let someDouble as Double where someDouble > 0: + println("a positive double value of \(someDouble)") + case is Double: + println("some other double value that I don't want to print") + case let someString as String: + println("a string value of \"\(someString)\"") + case let (x, y) as (Double, Double): + println("an (x, y) point at \(x), \(y)") + case let movie as Movie: + println("a movie called '\(movie.name)', dir. \(movie.director)") + default: + println("something else") } +} - // zero as an Int - // zero as a Double - // an integer value of 42 - // a positive double value of 3.14159 - // a string value of "hello" - // an (x, y) point at 3.0, 5.0 - // a movie called 'Ghostbusters', dir. Ivan Reitman -。 +// zero as an Int +// zero as a Double +// an integer value of 42 +// a positive double value of 3.14159 +// a string value of "hello" +// an (x, y) point at 3.0, 5.0 +// a movie called 'Ghostbusters', dir. Ivan Reitman +``` -> 注意: -> -在一个switch语句的case中使用强制形式的类型转换操作符(as, 而不是 as?)来检查和转换到一个明确的类型。在 switch case 语句的内容中这种检查总是安全的。 + +> 注意: +在一个switch语句的case中使用强制形式的类型转换操作符(as, 而不是 as?)来检查和转换到一个明确的类型。在 switch case 语句的内容中这种检查总是安全的。 \ No newline at end of file From c55862e5e0be3f70881f6d7935f33b0d3e26ee9f Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 19:37:12 +0800 Subject: [PATCH 04/14] fix 2.19 Nested --- source/chapter2/19_Nested_Types.md | 94 ++++++++++++++++-------------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/source/chapter2/19_Nested_Types.md b/source/chapter2/19_Nested_Types.md index 5edc7930..89d96cd9 100644 --- a/source/chapter2/19_Nested_Types.md +++ b/source/chapter2/19_Nested_Types.md @@ -1,14 +1,13 @@ -> 翻译:Lin-H - -> 校对:shinyzhu +> 翻译:Lin-H +> 校对:shinyzhu # 类型嵌套 ----------------- 本页包含内容: -- [类型嵌套实例](#nested_types_in_action) -- [类型嵌套的引用](#referring_to_nested_types) +- [类型嵌套实例](#nested_types_in_action) +- [类型嵌套的引用](#referring_to_nested_types) 枚举类型常被用于实现特定类或结构体的功能。也能够在有多种变量类型的环境中,方便地定义通用类或结构体来使用,为了实现这种功能,Swift允许你定义类型嵌套,可以在枚举类型、类和结构体中定义支持嵌套的类型。 @@ -21,41 +20,45 @@ 在`BlackjackCard`规则中,`Ace`牌可以表示1或者11,`Ace`牌的这一特征用一个嵌套在枚举型`Rank`的结构体`Values`来表示。 - struct BlackjackCard { - // 嵌套定义枚举型Suit - enum Suit: Character { - case Spades = "♠", Hearts = "♡", Diamonds = "♢", Clubs = "♣" - } - // 嵌套定义枚举型Rank - enum Rank: Int { - case Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten - case Jack, Queen, King, Ace - struct Values { - let first: Int, second: Int? - } - var values: Values { - switch self { - case .Ace: - return Values(first: 1, second: 11) - case .Jack, .Queen, .King: - return Values(first: 10, second: nil) - default: - return Values(first: self.toRaw(), second: nil) - } - } - } - // BlackjackCard 的属性和方法 - let rank: Rank, suit: Suit - var description: String { - var output = "suit is \(suit.toRaw())," - output += " value is \(rank.values.first)" - if let second = rank.values.second { - output += " or \(second)" - } - return output - } +```swift +struct BlackjackCard { + // 嵌套定义枚举型Suit + enum Suit: Character { + case Spades = "♠", Hearts = "♡", Diamonds = "♢", Clubs = "♣" } + // 嵌套定义枚举型Rank + enum Rank: Int { + case Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten + case Jack, Queen, King, Ace + struct Values { + let first: Int, second: Int? + } + var values: Values { + switch self { + case .Ace: + return Values(first: 1, second: 11) + case .Jack, .Queen, .King: + return Values(first: 10, second: nil) + default: + return Values(first: self.toRaw(), second: nil) + } + } + } + + // BlackjackCard 的属性和方法 + let rank: Rank, suit: Suit + var description: String { + var output = "suit is \(suit.toRaw())," + output += " value is \(rank.values.first)" + if let second = rank.values.second { + output += " or \(second)" + } + return output + } +} +``` + 枚举型的`Suit`用来描述扑克牌的四种花色,并分别用一个`Character`类型的值代表花色符号。 枚举型的`Rank`用来描述扑克牌从`Ace`~10,`J`,`Q`,`K`,13张牌,并分别用一个`Int`类型的值表示牌的面值。(这个`Int`类型的值不适用于`Ace`,`J`,`Q`,`K`的牌)。 @@ -71,9 +74,11 @@ 因为`BlackjackCard`是一个没有自定义构造函数的结构体,在[Memberwise Initializers for Structure Types](https://github.com/CocoaChina-editors/Welcome-to-Swift/blob/master/The%20Swift%20Programming%20Language/02Language%20Guide/14Initialization.md)中知道结构体有默认的成员构造函数,所以你可以用默认的`initializer`去初始化新的常量`theAceOfSpades`: - let theAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades) - println("theAceOfSpades: \(theAceOfSpades.description)") - // 打印出 "theAceOfSpades: suit is ♠, value is 1 or 11" +```swift +let theAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades) +println("theAceOfSpades: \(theAceOfSpades.description)") +// 打印出 "theAceOfSpades: suit is ♠, value is 1 or 11" +``` 尽管`Rank`和`Suit`嵌套在`BlackjackCard`中,但仍可被引用,所以在初始化实例时能够通过枚举类型中的成员名称单独引用。在上面的例子中`description`属性能正确得输出对`Ace`牌有1和11两个值。 @@ -82,7 +87,10 @@ 在外部对嵌套类型的引用,以被嵌套类型的名字为前缀,加上所要引用的属性名: - let heartsSymbol = BlackjackCard.Suit.Hearts.toRaw() - // 红心的符号 为 "♡" +```swift +let heartsSymbol = BlackjackCard.Suit.Hearts.toRaw() +// 红心的符号 为 "♡" +``` 对于上面这个例子,这样可以使`Suit`, `Rank`, 和 `Values`的名字尽可能的短,因为它们的名字会自然的由被定义的上下文来限定。 + From f82f20787152a8496861e8c4b5582ed5806892e9 Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 19:40:05 +0800 Subject: [PATCH 05/14] fix 2.20 extensions --- source/chapter2/19_Nested_Types.md | 1 + source/chapter2/20_Extensions.md | 53 ++++++++++++++---------------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/source/chapter2/19_Nested_Types.md b/source/chapter2/19_Nested_Types.md index 89d96cd9..6db51075 100644 --- a/source/chapter2/19_Nested_Types.md +++ b/source/chapter2/19_Nested_Types.md @@ -94,3 +94,4 @@ let heartsSymbol = BlackjackCard.Suit.Hearts.toRaw() 对于上面这个例子,这样可以使`Suit`, `Rank`, 和 `Values`的名字尽可能的短,因为它们的名字会自然的由被定义的上下文来限定。 +preview \ No newline at end of file diff --git a/source/chapter2/20_Extensions.md b/source/chapter2/20_Extensions.md index 9256d005..8c68a5dc 100644 --- a/source/chapter2/20_Extensions.md +++ b/source/chapter2/20_Extensions.md @@ -1,6 +1,5 @@ -> 翻译:lyuka - -> 校对:Hawstein +> 翻译:lyuka +> 校对:Hawstein #扩展(Extensions) ---- @@ -26,8 +25,7 @@ Swift 中的扩展可以: - 使一个已有类型符合某个接口 ->注意: -> +>注意: 如果你定义了一个扩展向一个已有类型添加新功能,那么这个新功能对该类型的所有已有实例中都是可用的,即使它们是在你的这个扩展的前面定义的。 @@ -35,7 +33,7 @@ Swift 中的扩展可以: 声明一个扩展使用关键字`extension`: -``` +```swift extension SomeType { // 加到SomeType的新功能写到这里 } @@ -43,7 +41,7 @@ extension SomeType { 一个扩展可以扩展一个已有类型,使其能够适配一个或多个协议(protocol)。当这种情况发生时,接口的名字应该完全按照类或结构体的名字的方式进行书写: -``` +```swift extension SomeType: SomeProtocol, AnotherProctocol { // 协议实现写到这里 } @@ -56,7 +54,7 @@ extension SomeType: SomeProtocol, AnotherProctocol { 扩展可以向已有类型添加计算型实例属性和计算型类型属性。下面的例子向 Swift 的内建`Double`类型添加了5个计算型实例属性,从而提供与距离单位协作的基本支持。 -``` +```swift extension Double { var km: Double { return self * 1_000.0 } var m : Double { return self } @@ -80,15 +78,14 @@ println("Three feet is \(threeFeet) meters") 这些属性是只读的计算型属性,所有从简考虑它们不用`get`关键字表示。它们的返回值是`Double`型,而且可以用于所有接受`Double`的数学计算中: -``` +```swift let aMarathon = 42.km + 195.m println("A marathon is \(aMarathon) meters long") // 打印输出:"A marathon is 42495.0 meters long" ``` ->注意: -> +>注意: 扩展可以添加新的计算属性,但是不可以添加存储属性,也不可以向已有属性添加属性观测器(property observers)。 @@ -98,14 +95,13 @@ println("A marathon is \(aMarathon) meters long") 扩展能向类中添加新的便利构造器,但是它们不能向类中添加新的指定构造器或析构函数。指定构造器和析构函数必须总是由原始的类实现来提供。 -> 注意: -> +> 注意: 如果你使用扩展向一个值类型添加一个构造器,该构造器向所有的存储属性提供默认值,而且没有定义任何定制构造器(custom initializers),那么对于来自你的扩展构造器中的值类型,你可以调用默认构造器(default initializers)和逐一成员构造器(memberwise initializers)。 正如在值类型的构造器授权中描述的,如果你已经把构造器写成值类型原始实现的一部分,上述规则不再适用。 下面的例子定义了一个用于描述几何矩形的定制结构体`Rect`。这个例子同时定义了两个辅助结构体`Size`和`Point`,它们都把`0.0`作为所有属性的默认值: -``` +```swift struct Size { var width = 0.0, height = 0.0 } @@ -120,7 +116,7 @@ struct Rect { 因为结构体`Rect`提供了其所有属性的默认值,所以正如默认构造器中描述的,它可以自动接受一个默认的构造器和一个成员级构造器。这些构造器可以用于构造新的`Rect`实例: -``` +```swift let defaultRect = Rect() let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0), size: Size(width: 5.0, height: 5.0)) @@ -128,7 +124,7 @@ let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0), 你可以提供一个额外的使用特殊中心点和大小的构造器来扩展`Rect`结构体: -``` +```swift extension Rect { init(center: Point, size: Size) { let originX = center.x - (size.width / 2) @@ -140,15 +136,14 @@ extension Rect { 这个新的构造器首先根据提供的`center`和`size`值计算一个合适的原点。然后调用该结构体自动的成员构造器`init(origin:size:)`,该构造器将新的原点和大小存到了合适的属性中: -``` +```swift let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: Size(width: 3.0, height: 3.0)) // centerRect的原点是 (2.5, 2.5),大小是 (3.0, 3.0) ``` ->注意: -> +>注意: 如果你使用扩展提供了一个新的构造器,你依旧有责任保证构造过程能够让所有实例完全初始化。 @@ -156,7 +151,7 @@ let centerRect = Rect(center: Point(x: 4.0, y: 4.0), 扩展可以向已有类型添加新的实例方法和类型方法。下面的例子向`Int`类型添加一个名为`repetitions`的新实例方法: -``` +```swift extension Int { func repetitions(task: () -> ()) { for i in 0..self { @@ -170,7 +165,7 @@ extension Int { 定义该扩展之后,你就可以对任意整数调用`repetitions`方法,实现的功能则是多次执行某任务: -``` +```swift 3.repetitions({ println("Hello!") }) @@ -181,7 +176,7 @@ extension Int { 可以使用 trailing 闭包使调用更加简洁: -``` +```swift 3.repetitions{ println("Goodbye!") } @@ -197,7 +192,7 @@ extension Int { 下面的例子向Swift的`Int`类型添加了一个新的名为`square`的修改方法,来实现一个原始值的平方计算: -``` +```swift extension Int { mutating func square() { self = self * self @@ -218,7 +213,7 @@ someInt.square() ...等等 -``` +```swift extension Int { subscript(digitIndex: Int) -> Int { var decimalBase = 1 @@ -240,7 +235,7 @@ extension Int { 如果该`Int`值没有足够的位数,即下标越界,那么上述实现的下标会返回0,因为它会在数字左边自动补0: -``` +```swift 746381295[9] //returns 0, 即等同于: 0746381295[9] @@ -251,7 +246,7 @@ extension Int { 扩展可以向已有的类、结构体和枚举添加新的嵌套类型: -``` +```swift extension Character { enum Kind { case Vowel, Consonant, Other @@ -276,7 +271,7 @@ extension Character { 现在,这个嵌套枚举可以和一个`Character`值联合使用了: -``` +```swift func printLetterKinds(word: String) { println("'\\(word)' is made up of the following kinds of letters:") for character in word { @@ -298,6 +293,6 @@ printLetterKinds("Hello") 函数`printLetterKinds`的输入是一个`String`值并对其字符进行迭代。在每次迭代过程中,考虑当前字符的`kind`计算属性,并打印出合适的类别描述。所以`printLetterKinds`就可以用来打印一个完整单词中所有字母的类型,正如上述单词`"hello"`所展示的。 ->注意: -> +>注意: 由于已知`character.kind`是`Character.Kind`型,所以`Character.Kind`中的所有成员值都可以使用`switch`语句里的形式简写,比如使用 `.Vowel`代替`Character.Kind.Vowel` + From 3ce6c6dd841f303523ba69f997c219c4cd5e76c2 Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 19:46:02 +0800 Subject: [PATCH 06/14] fix 2.21 protocols --- source/chapter2/21_Protocols.md | 744 +++++++++++++++++--------------- 1 file changed, 408 insertions(+), 336 deletions(-) diff --git a/source/chapter2/21_Protocols.md b/source/chapter2/21_Protocols.md index c8c4997d..2e73ccde 100644 --- a/source/chapter2/21_Protocols.md +++ b/source/chapter2/21_Protocols.md @@ -1,6 +1,5 @@ -> 翻译:geek5nan - -> 校对:dabing1022 +> 翻译:geek5nan +> 校对:dabing1022 # 协议 ----------------- @@ -30,22 +29,28 @@ `协议`的定义与类,结构体,枚举的定义非常相似,如下所示: - protocol SomeProtocol { - // 协议内容 - } +```swift +protocol SomeProtocol { + // 协议内容 +} +``` 在类,结构体,枚举的名称后加上`协议名称`,中间以冒号`:`分隔即可实现协议;实现多个协议时,各协议之间用逗号`,`分隔,如下所示: - struct SomeStructure: FirstProtocol, AnotherProtocol { - // 结构体内容 - } +```swift +struct SomeStructure: FirstProtocol, AnotherProtocol { + // 结构体内容 +} +``` 当某个类含有父类的同时并实现了协议,应当把父类放在所有的协议之前,如下所示: - class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol { - // 类的内容 - } +```swift +class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol { + // 类的内容 +} +``` ## 属性要求 @@ -54,46 +59,54 @@ 通常前置`var`关键字将属性声明为变量。在属性声明后写上`{ get set }`表示属性为可读写的。`{ get }`用来表示属性为可读的。即使你为可读的属性实现了`setter`方法,它也不会出错。 - protocol SomeProtocol { - var musBeSettable : Int { get set } - var doesNotNeedToBeSettable: Int { get } - } +```swift +protocol SomeProtocol { + var musBeSettable : Int { get set } + var doesNotNeedToBeSettable: Int { get } +} +``` 用类来实现协议时,使用`class`关键字来表示该属性为类成员;用结构体或枚举实现协议时,则使用`static`关键字来表示: - protocol AnotherProtocol { - class var someTypeProperty: Int { get set } - } +```swift +protocol AnotherProtocol { + class var someTypeProperty: Int { get set } +} - protocol FullyNamed { - var fullName: String { get } - } +protocol FullyNamed { + var fullName: String { get } +} +``` `FullyNamed`协议含有`fullName`属性。因此其`遵循者`必须含有一个名为`fullName`,类型为`String`的可读属性。 - struct Person: FullyNamed{ - var fullName: String - } - let john = Person(fullName: "John Appleseed") - //john.fullName 为 "John Appleseed" +```swift +struct Person: FullyNamed{ + var fullName: String +} +let john = Person(fullName: "John Appleseed") +//john.fullName 为 "John Appleseed" +``` `Person`结构体含有一个名为`fullName`的`存储型属性`,完整的`遵循`了协议。(*若协议未被完整遵循,编译时则会报错*)。 如下所示,`Startship`类`遵循`了`FullyNamed`协议: - class Starship: FullyNamed { - var prefix: String? - var name: String - init(name: String, prefix: String? = nil ) { - self.anme = name - self.prefix = prefix - } - var fullName: String { - return (prefix ? prefix ! + " " : " ") + name - } +```swift +class Starship: FullyNamed { + var prefix: String? + var name: String + init(name: String, prefix: String? = nil ) { + self.anme = name + self.prefix = prefix } - var ncc1701 = Starship(name: "Enterprise", prefix: "USS") - // ncc1701.fullName == "USS Enterprise" + var fullName: String { + return (prefix ? prefix ! + " " : " ") + name + } +} +var ncc1701 = Starship(name: "Enterprise", prefix: "USS") +// ncc1701.fullName == "USS Enterprise" +``` `Starship`类将`fullName`实现为可读的`计算型属性`。它的每一个实例都有一个名为`name`的必备属性和一个名为`prefix`的可选属性。 当`prefix`存在时,将`prefix`插入到`name`之前来为`Starship`构建`fullName`。 @@ -102,39 +115,42 @@ `协议`能够要求其`遵循者`必备某些特定的`实例方法`和`类方法`。协议方法的声明与普通方法声明相似,但它不需要`方法`内容。 -> 注意: -> +> 注意: 协议方法支持`变长参数(variadic parameter)`,不支持`默认参数(default parameter)`。 前置`class`关键字表示协议中的成员为`类成员`;当协议用于被`枚举`或`结构体`遵循时,则使用`static`关键字。如下所示: - protocol SomeProtocol { - class func someTypeMethod() - } +```swift +protocol SomeProtocol { + class func someTypeMethod() +} - protocol RandomNumberGenerator { - func random() -> Double - } +protocol RandomNumberGenerator { + func random() -> Double +} +``` `RandomNumberGenerator`协议要求其`遵循者`必须拥有一个名为`random`, 返回值类型为`Double`的实例方法。(我们假设随机数在[0,1]区间内)。 `LinearCongruentialGenerator`类`遵循`了`RandomNumberGenerator`协议,并提供了一个叫做*线性同余生成器(linear congruential generator)*的伪随机数算法。 - class LinearCongruentialGenerator: RandomNumberGenerator { - var lastRandom = 42.0 - let m = 139968.0 - let a = 3877.0 - let c = 29573.0 - func random() -> Double { - lastRandom = ((lastRandom * a + c) % m) - return lastRandom / m - } +```swift +class LinearCongruentialGenerator: RandomNumberGenerator { + var lastRandom = 42.0 + let m = 139968.0 + let a = 3877.0 + let c = 29573.0 + func random() -> Double { + lastRandom = ((lastRandom * a + c) % m) + return lastRandom / m } - let generator = LinearCongruentialGenerator() - println("Here's a random number: \(generator.random())") - // 输出 : "Here's a random number: 0.37464991998171" - println("And another one: \(generator.random())") - // 输出 : "And another one: 0.729023776863283" +} +let generator = LinearCongruentialGenerator() +println("Here's a random number: \(generator.random())") +// 输出 : "Here's a random number: 0.37464991998171" +println("And another one: \(generator.random())") +// 输出 : "And another one: 0.729023776863283" +``` ## 突变方法要求 @@ -143,34 +159,37 @@ (*译者注:类中的成员为`引用类型(Reference Type)`,可以方便的修改实例及其属性的值而无需改变类型;而`结构体`和`枚举`中的成员均为`值类型(Value Type)`,修改变量的值就相当于修改变量的类型,而`Swift`默认不允许修改类型,因此需要前置`mutating`关键字用来表示该`函数`中能够修改类型*) -> 注意: -> +> 注意: 用`class`实现协议中的`mutating`方法时,不用写`mutating`关键字;用`结构体`,`枚举`实现协议中的`mutating`方法时,必须写`mutating`关键字。 如下所示,`Togglable`协议含有`toggle`函数。根据函数名称推测,`toggle`可能用于**切换或恢复**某个属性的状态。`mutating`关键字表示它为`突变方法`: - protocol Togglable { - mutating func toggle() - } +```swift +protocol Togglable { + mutating func toggle() +} +``` 当使用`枚举`或`结构体`来实现`Togglabl`协议时,必须在`toggle`方法前加上`mutating`关键字。 如下所示,`OnOffSwitch`枚举`遵循`了`Togglable`协议,`On`,`Off`两个成员用于表示当前状态 - enum OnOffSwitch: Togglable { - case Off, On - mutating func toggle() { - switch self { - case Off: - self = On - case On: - self = Off - } +```swift +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 +} +var lightSwitch = OnOffSwitch.Off +lightSwitch.toggle() +//lightSwitch 现在的值为 .On +``` ## 协议类型 @@ -183,25 +202,26 @@ * 作为常量,变量,属性的类型 * 作为数组,字典或其他容器中的元素类型 -> 注意: -> +> 注意: 协议类型应与其他类型(Int,Double,String)的写法相同,使用驼峰式 - class Dice { - let sides: Int - let generator: RandomNumberGenerator - init(sides: Int, generator: RandomNumberGenerator) { - self.sides = sides - self.generator = generator - } - func roll() -> Int { - return Int(generator.random() * Double(sides)) +1 - } +```swift +class Dice { + let sides: Int + let generator: RandomNumberGenerator + init(sides: Int, generator: RandomNumberGenerator) { + self.sides = sides + self.generator = generator } + func roll() -> Int { + return Int(generator.random() * Double(sides)) +1 + } +} +``` 这里定义了一个名为 `Dice`的类,用来代表桌游中的N个面的骰子。 - `Dice`含有`sides`和`generator`两个属性,前者用来表示骰子有几个面,后者为骰子提供一个随机数生成器。由于后者为`RandomNumberGenerator`的协议类型。所以它能够被赋值为任意`遵循`该协议的类型。 +`Dice`含有`sides`和`generator`两个属性,前者用来表示骰子有几个面,后者为骰子提供一个随机数生成器。由于后者为`RandomNumberGenerator`的协议类型。所以它能够被赋值为任意`遵循`该协议的类型。 此外,使用`构造器(init)`来代替之前版本中的`setup`操作。构造器中含有一个名为`generator`,类型为`RandomNumberGenerator`的形参,使得它可以接收任意遵循`RandomNumberGenerator`协议的类型。 @@ -209,16 +229,18 @@ 如下所示,`LinearCongruentialGenerator`的实例作为随机数生成器传入`Dice`的`构造器` - var d6 = Dice(sides: 6,generator: LinearCongruentialGenerator()) - for _ in 1...5 { - println("Random dice roll is \(d6.roll())") - } - //输出结果 - //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 +```swift +var d6 = Dice(sides: 6,generator: LinearCongruentialGenerator()) +for _ in 1...5 { + println("Random dice roll is \(d6.roll())") +} +//输出结果 +//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 +``` ## 委托(代理)模式 @@ -231,55 +253,59 @@ 下文是两个基于骰子游戏的协议: - 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) - } +```swift +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) +} +``` `DiceGame`协议可以在任意含有骰子的游戏中实现,`DiceGameDelegate`协议可以用来追踪`DiceGame`的游戏过程。 如下所示,`SnakesAndLadders`是`Snakes and Ladders`(译者注:[控制流](05_Control_Flow.html)章节有该游戏的详细介绍)游戏的新版本。新版本使用`Dice`作为骰子,并且实现了`DiceGame`和`DiceGameDelegate`协议 - 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 > finalSquare: - continue gameLoop - default: - square += diceRoll - square += board[square] - } - } - delegate?.gameDIdEnd(self) - } +```swift +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 > finalSquare: + continue gameLoop + default: + square += diceRoll + square += board[square] + } + } + delegate?.gameDIdEnd(self) + } +} +``` 游戏的`初始化设置(setup)`被`SnakesAndLadders`类的`构造器(initializer)`实现。所有的游戏逻辑被转移到了`play`方法中。 -> 注意: -> +> 注意: 因为`delegate`并不是该游戏的必备条件,`delegate`被定义为遵循`DiceGameDelegate`协议的可选属性 `DicegameDelegate`协议提供了三个方法用来追踪游戏过程。被放置于游戏的逻辑中,即`play()`方法内。分别在游戏开始时,新一轮开始时,游戏结束时被调用。 @@ -288,23 +314,25 @@ 如下所示,`DiceGameTracker`遵循了`DiceGameDelegate`协议 - class DiceGameTracker: DiceGameDelegate { - var numberOfTurns = 0 - func gameDidStart(game: DiceGame) { - numberOfTurns = 0 - if game is SnakesAndLadders { - println("Started a new game of Snakes and Ladders") - } - println("The game is using a \(game.dice.sides)-sided dice") - } - func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) { - ++numberOfTurns - println("Rolled a \(diceRoll)") - } - func gameDidEnd(game: DiceGame) { - println("The game lasted for \(numberOfTurns) turns") - } - } +```swift +class DiceGameTracker: DiceGameDelegate { + var numberOfTurns = 0 + func gameDidStart(game: DiceGame) { + numberOfTurns = 0 + if game is SnakesAndLadders { + println("Started a new game of Snakes and Ladders") + } + println("The game is using a \(game.dice.sides)-sided dice") + } + func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) { + ++numberOfTurns + println("Rolled a \(diceRoll)") + } + func gameDidEnd(game: DiceGame) { + println("The game lasted for \(numberOfTurns) turns") + } +} +``` `DiceGameTracker`实现了`DiceGameDelegate`协议的方法要求,用来记录游戏已经进行的轮数。 当游戏开始时,`numberOfTurns`属性被赋值为0;在每新一轮中递加;游戏结束后,输出打印游戏的总轮数。 @@ -312,79 +340,91 @@ `DiceGameTracker`的运行情况,如下所示: - “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” +```swift +“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” +``` ## 在扩展中添加协议成员 即便无法修改源代码,依然可以通过`扩展(Extension)`来扩充已存在类型(*译者注: 类,结构体,枚举等*)。`扩展`可以为已存在的类型添加`属性`,`方法`,`下标`,`协议`等成员。详情请在[扩展](20_Extensions.html)章节中查看。 -> 注意: -> +> 注意: 通过`扩展`为已存在的类型`遵循`协议时,该类型的所有实例也会随之添加协议中的方法 `TextRepresentable`协议含有一个`asText`,如下所示: - protocol TextRepresentable { - func asText() -> String - } +```swift +protocol TextRepresentable { + func asText() -> String +} +``` 通过`扩展`为上一节中提到的`Dice`类遵循`TextRepresentable`协议 - extension Dice: TextRepresentable { - cun asText() -> String { - return "A \(sides)-sided dice" - } +```swift +extension Dice: TextRepresentable { + cun asText() -> String { + return "A \(sides)-sided dice" } +} +``` 从现在起,`Dice`类型的实例可被当作`TextRepresentable`类型: - let d12 = Dice(sides: 12,generator: LinearCongruentialGenerator()) - println(d12.asText()) - // 输出 "A 12-sided dice" +```swift +let d12 = Dice(sides: 12,generator: LinearCongruentialGenerator()) +println(d12.asText()) +// 输出 "A 12-sided dice" +``` `SnakesAndLadders`类也可以通过`扩展`的方式来遵循协议: - extension SnakeAndLadders: TextRepresentable { - func asText() -> String { - return "A game of Snakes and Ladders with \(finalSquare) squares" - } +```swift +extension SnakeAndLadders: TextRepresentable { + func asText() -> String { + return "A game of Snakes and Ladders with \(finalSquare) squares" } - println(game.asText()) - // 输出 "A game of Snakes and Ladders with 25 squares" +} +println(game.asText()) +// 输出 "A game of Snakes and Ladders with 25 squares" +``` ## 通过延展补充协议声明 当一个类型已经实现了协议中的所有要求,却没有声明时,可以通过`扩展`来补充协议声明: - struct Hamster { - var name: String - func asText() -> String { - return "A hamster named \(name)" - } +```swift +struct Hamster { + var name: String + func asText() -> String { + return "A hamster named \(name)" } - extension Hamster: TextRepresentabl {} +} +extension Hamster: TextRepresentabl {} +``` 从现在起,`Hamster`的实例可以作为`TextRepresentable`类型使用 - let simonTheHamster = Hamster(name: "Simon") - let somethingTextRepresentable: TextRepresentabl = simonTheHamester - println(somethingTextRepresentable.asText()) - // 输出 "A hamster named Simon" +```swift +let simonTheHamster = Hamster(name: "Simon") +let somethingTextRepresentable: TextRepresentabl = simonTheHamester +println(somethingTextRepresentable.asText()) +// 输出 "A hamster named Simon" +``` -> 注意: -> +> 注意: 即时满足了协议的所有要求,类型也不会自动转变,因此你必须为它做出明显的协议声明 @@ -392,16 +432,20 @@ 协议类型可以被集合使用,表示集合中的元素均为协议类型: - let things: TextRepresentable[] = [game,d12,simoTheHamster] +```swift +let things: TextRepresentable[] = [game,d12,simoTheHamster] +``` 如下所示,`things`数组可以被直接遍历,并调用其中元素的`asText()`函数: - for thing in things { - println(thing.asText()) - } - // A game of Snakes and Ladders with 25 squares - // A 12-sided dice - // A hamster named Simon +```swift +for thing in things { + println(thing.asText()) +} +// A game of Snakes and Ladders with 25 squares +// A 12-sided dice +// A hamster named Simon +``` `thing`被当做是`TextRepresentable`类型而不是`Dice`,`DiceGame`,`Hamster`等类型。因此能且仅能调用`asText`方法 @@ -410,36 +454,42 @@ 协议能够*继承*一到多个其他协议。语法与类的继承相似,多个协议间用逗号`,`分隔 - protocol InheritingProtocol: SomeProtocol, AnotherProtocol { - // 协议定义 - } +```swift +protocol InheritingProtocol: SomeProtocol, AnotherProtocol { + // 协议定义 +} +``` 如下所示,`PrettyTextRepresentable`协议继承了`TextRepresentable`协议 - protocol PrettyTextRepresentable: TextRepresentable { - func asPrettyText() -> String - } +```swift +protocol PrettyTextRepresentable: TextRepresentable { + func asPrettyText() -> String +} +``` `遵循``PrettyTextRepresentable`协议的同时,也需要`遵循`TextRepresentable`协议。 如下所示,用`扩展`为`SnakesAndLadders`遵循`PrettyTextRepresentable`协议: - extension SnakesAndLadders: PrettyTextRepresentable { - func asPrettyText() -> String { - var output = asText() + ":\n" - for index in 1...finalSquare { - switch board[index] { - case let ladder where ladder > 0: - output += "▲ " - case let snake where snake < 0: - output += "▼ " - default: - output += "○ " - } - } - return output - } - } +```swift +extension SnakesAndLadders: PrettyTextRepresentable { + func asPrettyText() -> String { + var output = asText() + ":\n" + for index in 1...finalSquare { + switch board[index] { + case let ladder where ladder > 0: + output += "▲ " + case let snake where snake < 0: + output += "▼ " + default: + output += "○ " + } + } + return output + } +} +``` 在`for in`中迭代出了`board`数组中的每一个元素: @@ -449,9 +499,11 @@ 任意`SankesAndLadders`的实例都可以使用`asPrettyText()`方法。 - println(game.asPrettyText()) - // A game of Snakes and Ladders with 25 squares: - // ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○ +```swift +println(game.asPrettyText()) +// A game of Snakes and Ladders with 25 squares: +// ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○ +``` ## 协议合成 @@ -460,29 +512,30 @@ 举个例子: - 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) { - println("Happy birthday \(celebrator.name) - you're \(celebrator.age)!") - } - let birthdayPerson = Person(name: "Malcolm", age: 21) - wishHappyBirthday(birthdayPerson) - // 输出 "Happy birthday Malcolm - you're 21! +```swift +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) { + println("Happy birthday \(celebrator.name) - you're \(celebrator.age)!") +} +let birthdayPerson = Person(name: "Malcolm", age: 21) +wishHappyBirthday(birthdayPerson) +// 输出 "Happy birthday Malcolm - you're 21! +``` `Named`协议包含`String`类型的`name`属性;`Aged`协议包含`Int`类型的`age`属性。`Person`结构体`遵循`了这两个协议。 `wishHappyBirthday`函数的形参`celebrator`的类型为`protocol`。可以传入任意`遵循`这两个协议的类型的实例 -> 注意: -> +> 注意: `协议合成`并不会生成一个新协议类型,而是将多个协议合成为一个临时的协议,超出范围后立即失效。 @@ -494,57 +547,64 @@ * `as?`返回一个可选值,当实例`遵循`协议时,返回该协议类型;否则返回`nil` * `as`用以强制向下转换型。 -``` +```swift @objc protocol HasArea { - var area: Double { get } + var area: Double { get } } ``` -> 注意: -> +> 注意: `@objc`用来表示协议是可选的,也可以用来表示暴露给`Objective-C`的代码,此外,`@objc`型协议只对`类`有效,因此只能在`类`中检查协议的一致性。详情查看*[Using Siwft with Cocoa and Objectivei-c](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)*。 - class Circle: HasArea { - let pi = 3.1415927 - var radius: Double - var area:≈radius } - init(radius: Double) { self.radius = radius } - } - class Country: HasArea { - var area: Double - init(area: Double) { self.area = area } - } +```swift +class Circle: HasArea { + let pi = 3.1415927 + var radius: Double + var area:≈radius } + init(radius: Double) { self.radius = radius } +} +class Country: HasArea { + var area: Double + init(area: Double) { self.area = area } +} +``` `Circle`和`Country`都遵循了`HasArea`协议,前者把`area`写为计算型属性(computed property),后者则把`area`写为存储型属性(stored property)。 如下所示,`Animal`类没有实现任何协议 - class Animal { - var legs: Int - init(legs: Int) { self.legs = legs } - } +```swift +class Animal { + var legs: Int + init(legs: Int) { self.legs = legs } +} +``` `Circle,Country,Animal`并没有一个相同的基类,所以采用`AnyObject`类型的数组来装载在他们的实例,如下所示: - let objects: AnyObject[] = [ - Circle(radius: 2.0), - Country(area: 243_610), - Animal(legs: 4) - ] +```swift +let objects: AnyObject[] = [ + Circle(radius: 2.0), + Country(area: 243_610), + Animal(legs: 4) +] +``` 如下所示,在迭代时检查`object`数组的元素是否`遵循`了`HasArea`协议: - for object in objects { - if let objectWithArea = object as? HasArea { - println("Area is \(objectWithArea.area)") - } else { - println("Something that doesn't have an area") - } - } - // Area is 12.5663708 - // Area is 243610.0 - // Something that doesn't have an area +```swift +for object in objects { + if let objectWithArea = object as? HasArea { + println("Area is \(objectWithArea.area)") + } else { + println("Something that doesn't have an area") + } +} +// Area is 12.5663708 +// Area is 243610.0 +// Something that doesn't have an area +``` 当数组中的元素遵循`HasArea`协议时,通过`as?`操作符将其`可选绑定(optional binding)`到`objectWithArea`常量上。 @@ -559,36 +619,38 @@ 像`someOptionalMethod?(someArgument)`一样,你可以在可选方法名称后加上`?`来检查该方法是否被实现。`可选方法`和`可选属性`都会返回一个`可选值(optional value)`,当其不可访问时,`?`之后语句不会执行,并返回`nil`。 -> 注意: -> +> 注意: 可选协议只能在含有`@objc`前缀的协议中生效。且`@objc`的协议只能被`类`遵循。 `Counter`类使用`CounterDataSource`类型的外部数据源来提供`增量值(increment amount)`,如下所示: - @objc protocol CounterDataSource { - @optional func incrementForCount(count: Int) -> Int - @optional var fixedIncrement: Int { get } - } +```swift +@objc protocol CounterDataSource { + @optional func incrementForCount(count: Int) -> Int + @optional var fixedIncrement: Int { get } +} +``` `CounterDataSource`含有`incrementForCount`的`可选方法`和`fiexdIncrement`的`可选属性`。 -> 注意: -> +> 注意: `CounterDataSource`中的属性和方法都是可选的,因此可以在类中声明但不实现这些成员,尽管技术上允许这样做,不过最好不要这样写。 `Counter`类含有`CounterDataSource?`类型的可选属性`dataSource`,如下所示: - @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 - } - } - } +```swift +@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 + } + } +} +``` `count`属性用于存储当前的值,`increment`方法用来为`count`赋值。 @@ -603,47 +665,57 @@ `ThreeSource`实现了`CounterDataSource`协议,如下所示: - class ThreeSource: CounterDataSource { - let fixedIncrement = 3 - } +```swift +class ThreeSource: CounterDataSource { + let fixedIncrement = 3 +} +``` 使用`ThreeSource`作为数据源开实例化一个`Counter`: - var counter = Counter() - counter.dataSource = ThreeSource() - for _ in 1...4 { - counter.increment() - println(counter.count) - } - // 3 - // 6 - // 9 - // 12 +```swift +var counter = Counter() +counter.dataSource = ThreeSource() +for _ in 1...4 { + counter.increment() + println(counter.count) +} +// 3 +// 6 +// 9 +// 12 +``` `TowardsZeroSource`实现了`CounterDataSource`协议中的`incrementForCount`方法,如下所示: - class TowardsZeroSource: CounterDataSource { - func incrementForCount(count: Int) -> Int { - if count == 0 { - return 0 - } else if count < 0 { - return 1 - } else { - return -1 - } - } - } +```swift +class TowardsZeroSource: CounterDataSource { +func incrementForCount(count: Int) -> Int { + if count == 0 { + return 0 + } else if count < 0 { + return 1 + } else { + return -1 + } + } +} +``` 下边是执行的代码: - counter.count = -4 - counter.dataSource = TowardsZeroSource() - for _ in 1...5 { - counter.increment() - println(counter.count) - } - // -3 - // -2 - // -1 - // 0 - // 0 +```swift +counter.count = -4 +counter.dataSource = TowardsZeroSource() +for _ in 1...5 { + counter.increment() + println(counter.count) +} +// -3 +// -2 +// -1 +// 0 +// 0 +``` + +preview \ No newline at end of file From 5f20e3f4af695d50b4daed240f787bfc2652ae32 Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 19:51:22 +0800 Subject: [PATCH 07/14] fix 2.22 generices --- source/chapter2/22_Generics.md | 406 ++++++++++++++++++--------------- 1 file changed, 226 insertions(+), 180 deletions(-) diff --git a/source/chapter2/22_Generics.md b/source/chapter2/22_Generics.md index e2be186a..7ec8b96c 100644 --- a/source/chapter2/22_Generics.md +++ b/source/chapter2/22_Generics.md @@ -1,6 +1,5 @@ -> 翻译:takalard - -> 校对:lifedim +> 翻译:takalard +> 校对:lifedim # 泛型 @@ -26,42 +25,48 @@ 这里是一个标准的,非泛型函数`swapTwoInts`,用来交换两个Int值: - func swapTwoInts(inout a: Int, inout b: Int) - let temporaryA = a - a = b - b = temporaryA - } +```swift +func swapTwoInts(inout a: Int, inout b: Int) + let temporaryA = a + a = b + b = temporaryA +} +``` 这个函数使用写入读出(in-out)参数来交换`a`和`b`的值,请参考[写入读出参数][1]。 `swapTwoInts`函数可以交换`b`的原始值到`a`,也可以交换a的原始值到`b`,你可以调用这个函数交换两个`Int`变量值: - var someInt = 3 - var anotherInt = 107 - swapTwoInts(&someInt, &anotherInt) - println("someInt is now \(someInt), and anotherInt is now \(anotherInt)") - // 输出 "someInt is now 107, and anotherInt is now 3" +```swift +var someInt = 3 +var anotherInt = 107 +swapTwoInts(&someInt, &anotherInt) +println("someInt is now \(someInt), and anotherInt is now \(anotherInt)") +// 输出 "someInt is now 107, and anotherInt is now 3" +``` `swapTwoInts`函数是非常有用的,但是它只能交换`Int`值,如果你想要交换两个`String`或者`Double`,就不得不写更多的函数,如 `swapTwoStrings`和`swapTwoDoublesfunctions `,如同如下所示: - func swapTwoStrings(inout a: String, inout b: String) { - let temporaryA = a - a = b - b = temporaryA - } +```swift +func swapTwoStrings(inout a: String, inout b: String) { + let temporaryA = a + a = b + b = temporaryA +} - func swapTwoDoubles(inout a: Double, inout b: Double) { - let temporaryA = a - a = b - b = temporaryA - } +func swapTwoDoubles(inout a: Double, inout b: Double) { + let temporaryA = a + a = b + b = temporaryA +} +``` 你可能注意到 `swapTwoInts`、 `swapTwoStrings`和`swapTwoDoubles`函数功能都是相同的,唯一不同之处就在于传入的变量类型不同,分别是`Int`、`String`和`Double`。 但实际应用中通常需要一个用处更强大并且尽可能的考虑到更多的灵活性单个函数,可以用来交换两个任何类型值,很幸运的是,泛型代码帮你解决了这种问题。(一个这种泛型函数后面已经定义好了。) ->注意: +>注意: 在所有三个函数中,`a`和`b`的类型是一样的。如果`a`和`b`不是相同的类型,那它们俩就不能互换值。Swift 是类型安全的语言,所以它不允许一个`String`类型的变量和一个`Double`类型的变量互相交换值。如果一定要做,Swift 将报编译错误。 @@ -69,16 +74,20 @@ `泛型函数`可以工作于任何类型,这里是一个上面`swapTwoInts`函数的泛型版本,用于交换两个值: - func swapTwoValues(inout a: T, inout b: T) { - let temporaryA = a - a = b - b = temporaryA - } +```swift +func swapTwoValues(inout a: T, inout b: T) { + let temporaryA = a + a = b + b = temporaryA +} +``` `swapTwoValues`函数主体和`swapTwoInts`函数是一样的,它只在第一行稍微有那么一点点不同于`swapTwoInts`,如下所示: - func swapTwoInts(inout a: Int, inout b: Int) - func swapTwoValues(inout a: T, inout b: T) +```swift +func swapTwoInts(inout a: Int, inout b: Int) +func swapTwoValues(inout a: T, inout b: T) +``` 这个函数的泛型版本使用了占位类型名字(通常此情况下用字母`T`来表示)来代替实际类型名(如`In`、`String`或`Doubl`)。占位类型名没有提示`T`必须是什么类型,但是它提示了`a`和`b`必须是同一类型`T`,而不管`T`表示什么类型。只有`swapTwoValues`函数在每次调用时所传入的实际类型才能决定`T`所代表的类型。 @@ -89,18 +98,22 @@ 在下面的两个例子中,`T`分别代表`Int`和`String`: - var someInt = 3 - var anotherInt = 107 - swapTwoValues(&someInt, &anotherInt) - // someInt is now 107, and anotherInt is now 3 +```swift +var someInt = 3 +var anotherInt = 107 +swapTwoValues(&someInt, &anotherInt) +// someInt is now 107, and anotherInt is now 3 +``` - var someString = "hello" - var anotherString = "world" - swapTwoValues(&someString, &anotherString) - // someString is now "world", and anotherString is now "hello" +```swift +var someString = "hello" +var anotherString = "world" +swapTwoValues(&someString, &anotherString) +// someString is now "world", and anotherString is now "hello" +``` ->注意 +>注意 上面定义的函数`swapTwoValues`是受`swap`函数启发而实现的。`swap`函数存在于 Swift 标准库,并可以在其它类中任意使用。如果你在自己代码中需要类似`swapTwoValues`函数的功能,你可以使用已存在的交换函数`swap`函数。 @@ -119,7 +132,7 @@ 如果你使用多个参数定义更复杂的泛型函数或泛型类型,那么使用更多的描述类型参数是非常有用的。例如,Swift 字典(Dictionary)类型有两个类型参数,一个是键,另外一个是值。如果你自己写字典,你或许会定义这两个类型参数为`KeyType`和`ValueType`,用来记住它们在你的泛型代码中的作用。 ->注意 +>注意 请始终使用大写字母开头的驼峰式命名法(例如`T`和`KeyType`)来给类型参数命名,以表明它们是类型的占位符,而非类型值。 @@ -130,7 +143,7 @@ 这部分向你展示如何写一个泛型集类型--`Stack`(栈)。一个栈是一系列值域的集合,和`Array`(数组)类似,但其是一个比 Swift 的`Array`类型更多限制的集合。一个数组可以允许其里面任何位置的插入/删除操作,而栈,只允许在集合的末端添加新的项(如同*push*一个新值进栈)。同样的一个栈也只能从末端移除项(如同*pop*一个值出栈)。 ->注意 +>注意 栈的概念已被`UINavigationController`类使用来模拟试图控制器的导航结构。你通过调用`UINavigationController`的`pushViewController:animated:`方法来为导航栈添加(add)新的试图控制器;而通过`popViewControllerAnimated:`的方法来从导航栈中移除(pop)某个试图控制器。每当你需要一个严格的`后进先出`方式来管理集合,堆栈都是最实用的模型。 下图展示了一个栈的压栈(push)/出栈(pop)的行为: @@ -145,15 +158,17 @@ 这里展示了如何写一个非泛型版本的栈,`Int`值型的栈: - struct IntStack { - var items = Int[]() - mutating func push(item: Int) { - items.append(item) - } - mutating func pop() -> Int { - return items.removeLast() - } - } +```swift +struct IntStack { + var items = Int[]() + mutating func push(item: Int) { + items.append(item) + } + mutating func pop() -> Int { + return items.removeLast() + } +} +``` 这个结构体在栈中使用一个`Array`性质的`items`存储值。`Stack`提供两个方法:`push`和`pop`,从栈中压进一个值和移除一个值。这些方法标记为可变的,因为他们需要修改(或*转换*)结构体的`items`数组。 @@ -162,15 +177,17 @@ 这里是一个相同代码的泛型版本: - struct Stack { - var items = T[]() - mutating func push(item: T) { - items.append(item) - } - mutating func pop() -> T { - return items.removeLast() - } - } +```swift +struct Stack { + var items = T[]() + mutating func push(item: T) { + items.append(item) + } + mutating func pop() -> T { + return items.removeLast() + } +} +``` 注意到`Stack`的泛型版本基本上和非泛型版本相同,但是泛型版本的占位类型参数为T代替了实际`Int`类型。这种类型参数包含在一对尖括号里(``),紧随在结构体名字后面。 @@ -183,12 +200,14 @@ 当创建一个新单例并初始化时, 通过用一对紧随在类型名后的尖括号里写出实际指定栈用到类型,创建一个`Stack`实例,同创建`Array`和`Dictionary`一样: - var stackOfStrings = Stack() - stackOfStrings.push("uno") - stackOfStrings.push("dos") - stackOfStrings.push("tres") - stackOfStrings.push("cuatro") - // 现在栈已经有4个string了 +```swift +var stackOfStrings = Stack() +stackOfStrings.push("uno") +stackOfStrings.push("dos") +stackOfStrings.push("tres") +stackOfStrings.push("cuatro") +// 现在栈已经有4个string了 +``` 下图将展示`stackOfStrings`如何`push`这四个值进栈的过程: @@ -196,8 +215,10 @@ 从栈中`pop`并移除值"cuatro": - let fromTheTop = stackOfStrings.pop() - // fromTheTop is equal to "cuatro", and the stack now contains 3 strings +```swift +let fromTheTop = stackOfStrings.pop() +// fromTheTop is equal to "cuatro", and the stack now contains 3 strings +``` 下图展示了如何从栈中pop一个值的过程: ![此处输入图片的描述][4] @@ -219,9 +240,11 @@ 你可以写一个在一个类型参数名后面的类型约束,通过冒号分割,来作为类型参数链的一部分。这种作用于泛型函数的类型约束的基础语法如下所示(和泛型类型的语法相同): - func someFunction(someT: T, someU: U) { - // function body goes here - } +```swift +func someFunction(someT: T, someU: U) { + // function body goes here +} +``` 上面这个假定函数有两个类型参数。第一个类型参数`T`,有一个需要`T`必须是`SomeClass`子类的类型约束;第二个类型参数`U`,有一个需要`U`必须遵循`SomeProtocol`协议的类型约束。 @@ -229,36 +252,42 @@ 这里有个名为`findStringIndex`的非泛型函数,该函数功能是去查找包含一给定`String`值的数组。若查找到匹配的字符串,`findStringIndex`函数返回该字符串在数组中的索引值(`Int`),反之则返回`nil`: - func findStringIndex(array: String[], valueToFind: String) -> Int? { - for (index, value) in enumerate(array) { - if value == valueToFind { - return index - } - } - return nil - } +```swift +func findStringIndex(array: String[], valueToFind: String) -> Int? { + for (index, value) in enumerate(array) { + if value == valueToFind { + return index + } + } + return nil +} +``` `findStringIndex`函数可以作用于查找一字符串数组中的某个字符串: - let strings = ["cat", "dog", "llama", "parakeet", "terrapin"] - if let foundIndex = findStringIndex(strings, "llama") { - println("The index of llama is \(foundIndex)") - } - // 输出 "The index of llama is 2" +```swift +let strings = ["cat", "dog", "llama", "parakeet", "terrapin"] +if let foundIndex = findStringIndex(strings, "llama") { + println("The index of llama is \(foundIndex)") +} +// 输出 "The index of llama is 2" +``` 如果只是针对字符串而言查找在数组中的某个值的索引,用处不是很大,不过,你可以写出相同功能的泛型函数`findIndex`,用某个类型`T`值替换掉提到的字符串。 这里展示如何写一个你或许期望的`findStringIndex`的泛型版本`findIndex`。请注意这个函数仍然返回`Int`,是不是有点迷惑呢,而不是泛型类型?那是因为函数返回的是一个可选的索引数,而不是从数组中得到的一个可选值。需要提醒的是,这个函数不会编译,原因在例子后面会说明: - func findIndex(array: T[], valueToFind: T) -> Int? { - for (index, value) in enumerate(array) { - if value == valueToFind { - return index - } - } - return nil - } +```swift +func findIndex(array: T[], valueToFind: T) -> Int? { + for (index, value) in enumerate(array) { + if value == valueToFind { + return index + } + } + return nil +} +``` 上面所写的函数不会编译。这个问题的位置在等式的检查上,`“if value == valueToFind”`。不是所有的 Swift 中的类型都可以用等式符(==)进行比较。例如,如果你创建一个你自己的类或结构体来表示一个复杂的数据模型,那么 Swift 没法猜到对于这个类或结构体而言“等于”的意思。正因如此,这部分代码不能可能保证工作于每个可能的类型`T`,当你试图编译这部分代码时估计会出现相应的错误。 @@ -266,24 +295,28 @@ 任何`Equatable`类型都可以安全的使用在`findIndex`函数中,因为其保证支持等式操作。为了说明这个事实,当你定义一个函数时,你可以写一个`Equatable`类型约束作为类型参数定义的一部分: - func findIndex(array: T[], valueToFind: T) -> Int? { - for (index, value) in enumerate(array) { - if value == valueToFind { - return index - } - } - return nil - } +```swift +func findIndex(array: T[], valueToFind: T) -> Int? { + for (index, value) in enumerate(array) { + if value == valueToFind { + return index + } + } + return nil +} +``` `findIndex`中这个单个类型参数写做:`T: Equatable`,也就意味着“任何T类型都遵循`Equatable`协议”。 `findIndex`函数现在则可以成功的编译过,并且作用于任何遵循`Equatable`的类型,如`Double`或`String`: - let doubleIndex = findIndex([3.14159, 0.1, 0.25], 9.3) - // doubleIndex is an optional Int with no value, because 9.3 is not in the array - let stringIndex = findIndex(["Mike", "Malcolm", "Andrea"], "Andrea") - // stringIndex is an optional Int containing a value of 2 +```swift +let doubleIndex = findIndex([3.14159, 0.1, 0.25], 9.3) +// doubleIndex is an optional Int with no value, because 9.3 is not in the array +let stringIndex = findIndex(["Mike", "Malcolm", "Andrea"], "Andrea") +// stringIndex is an optional Int containing a value of 2 +``` ##关联类型 @@ -294,12 +327,14 @@ 这里是一个`Container`协议的例子,定义了一个ItemType关联类型: - protocol Container { - typealias ItemType - mutating func append(item: ItemType) - var count: Int { get } - subscript(i: Int) -> ItemType { get } - } +```swift +protocol Container { + typealias ItemType + mutating func append(item: ItemType) + var count: Int { get } + subscript(i: Int) -> ItemType { get } +} +``` `Container`协议定义了三个任何容器必须支持的兼容要求: @@ -317,27 +352,29 @@ 这里是一个早前IntStack类型的非泛型版本,适用于遵循Container协议: - struct IntStack: Container { - // original IntStack implementation - var items = Int[]() - mutating func push(item: Int) { - items.append(item) - } - mutating func pop() -> Int { - return items.removeLast() - } - // conformance to the Container protocol - typealias ItemType = Int - mutating func append(item: Int) { - self.push(item) - } - var count: Int { - return items.count - } - subscript(i: Int) -> Int { - return items[i] - } - } +```swift +struct IntStack: Container { + // original IntStack implementation + var items = Int[]() + mutating func push(item: Int) { + items.append(item) + } + mutating func pop() -> Int { + return items.removeLast() + } + // conformance to the Container protocol + typealias ItemType = Int + mutating func append(item: Int) { + self.push(item) + } + var count: Int { + return items.count + } + subscript(i: Int) -> Int { + return items[i] + } +} +``` `IntStack`类型实现了`Container`协议的所有三个要求,在`IntStack`类型的每个包含部分的功能都满足这些要求。 @@ -348,26 +385,28 @@ 你也可以生成遵循`Container`协议的泛型`Stack`类型: - struct Stack: Container { - // original Stack implementation - var items = T[]() - mutating func push(item: T) { - items.append(item) - } - mutating func pop() -> T { - return items.removeLast() - } - // conformance to the Container protocol - mutating func append(item: T) { - self.push(item) - } - var count: Int { - return items.count - } - subscript(i: Int) -> T { - return items[i] - } - } +```swift +struct Stack: Container { + // original Stack implementation + var items = T[]() + mutating func push(item: T) { + items.append(item) + } + mutating func pop() -> T { + return items.removeLast() + } + // conformance to the Container protocol + mutating func append(item: T) { + self.push(item) + } + var count: Int { + return items.count + } + subscript(i: Int) -> T { + return items[i] + } +} +``` 这个时候,占位类型参数`T`被用作`append`方法的item参数和下标的返回类型。Swift 因此可以推断出被用作这个特定容器的`ItemType`的`T`的合适类型。 @@ -378,7 +417,9 @@ Swift的`Array`已经提供`append`方法,一个`count`属性和通过下标来查找一个自己的元素。这三个功能都达到`Container`协议的要求。也就意味着你可以扩展`Array`去遵循`Container`协议,只要通过简单声明`Array`适用于该协议而已。如何实践这样一个空扩展,在[使用扩展来声明协议的采纳][7]中有描述这样一个实现一个空扩展的行为: - extension Array: Container {} +```swift +extension Array: Container {} +``` 如同上面的泛型`Stack`类型一样,`Array的append`方法和下标保证`Swift`可以推断出`ItemType`所使用的适用的类型。定义了这个扩展后,你可以将任何`Array`当作`Container`来使用。 @@ -393,27 +434,29 @@ Swift的`Array`已经提供`append`方法,一个`count`属性和通过下标 这两个容器可以被检查出是否是相同类型的容器(虽然它们可以是),但他们确实拥有相同类型的元素。这个需求通过一个类型约束和`where`语句结合来表示: - func allItemsMatch< - C1: Container, C2: Container - where C1.ItemType == C2.ItemType, C1.ItemType: Equatable> - (someContainer: C1, anotherContainer: C2) -> Bool { +```swift +func allItemsMatch< + C1: Container, C2: Container + where C1.ItemType == C2.ItemType, C1.ItemType: Equatable> + (someContainer: C1, anotherContainer: C2) -> Bool { - // check that both containers contain the same number of items - if someContainer.count != anotherContainer.count { - return false - } + // check that both containers contain the same number of items + if someContainer.count != anotherContainer.count { + return false + } - // check each pair of items to see if they are equivalent - for i in 0..someContainer.count { - if someContainer[i] != anotherContainer[i] { - return false - } - } + // check each pair of items to see if they are equivalent + for i in 0..someContainer.count { + if someContainer[i] != anotherContainer[i] { + return false + } + } - // all items match, so return true - return true + // all items match, so return true + return true - } +} +``` 这个函数用了两个参数:`someContainer`和`anotherContainer`。`someContainer`参数是类型`C1`,`anotherContainer`参数是类型`C2`。`C1`和`C2`是容器的两个占位类型参数,决定了这个函数何时被调用。 @@ -446,19 +489,21 @@ Swift的`Array`已经提供`append`方法,一个`count`属性和通过下标 这里演示了allItemsMatch函数运算的过程: - var stackOfStrings = Stack() - stackOfStrings.push("uno") - stackOfStrings.push("dos") - stackOfStrings.push("tres") +```swift +var stackOfStrings = Stack() +stackOfStrings.push("uno") +stackOfStrings.push("dos") +stackOfStrings.push("tres") - var arrayOfStrings = ["uno", "dos", "tres"] +var arrayOfStrings = ["uno", "dos", "tres"] - if allItemsMatch(stackOfStrings, arrayOfStrings) { - println("All items match.") - } else { - println("Not all items match.") - } - // 输出 "All items match." +if allItemsMatch(stackOfStrings, arrayOfStrings) { + println("All items match.") +} else { + println("Not all items match.") +} +// 输出 "All items match." +``` 上面的例子创建一个`Stack`单例来存储`String`,然后压了三个字符串进栈。这个例子也创建了一个`Array`单例,并初始化包含三个同栈里一样的原始字符串。即便栈和数组否是不同的类型,但他们都遵循`Container`协议,而且他们都包含同样的类型值。你因此可以调用`allItemsMatch`函数,用这两个容器作为它的参数。在上面的例子中,`allItemsMatch`函数正确的显示了所有的这两个容器的`items`匹配。 @@ -470,3 +515,4 @@ Swift的`Array`已经提供`append`方法,一个`count`属性和通过下标 [6]: ../chapter2/21_Protocols.html [7]: ../chapter2/21_Protocols.html [8]: #type_constraints + From 395e6b34c3487a6d0112fc9661f287757e8fbc18 Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 19:56:30 +0800 Subject: [PATCH 08/14] fix 2.23 advaced operators --- source/chapter2/23_Advanced_Operators.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/source/chapter2/23_Advanced_Operators.md b/source/chapter2/23_Advanced_Operators.md index 7912d18c..d85f31a5 100644 --- a/source/chapter2/23_Advanced_Operators.md +++ b/source/chapter2/23_Advanced_Operators.md @@ -1,6 +1,5 @@ -> 翻译:xielingwang - -> 校对:numbbbbb +> 翻译:xielingwang +> 校对:numbbbbb # 高级运算符 ----------------- @@ -305,8 +304,7 @@ let y = x &/ 0 查阅Swift运算符的优先级和结合性的完整列表,请看[表达式](../chapter3/04_Expressions.html)。 -> 注意: -> +> 注意: Swift的运算符较C语言和Objective-C来得更简单和保守,这意味着跟基于C的语言可能不一样。所以,在移植已有代码到Swift时,注意去确保代码按你想的那样去执行。 @@ -329,7 +327,6 @@ struct Vector2D { 该运算符函数定义了一个全局的`+`函数,这个函数需要两个`Vector2D`类型的参数,返回值也是`Vector2D`类型。需要定义和实现一个中置运算的时候,在关键字`func`之前写上属性 `@infix` 就可以了。 - 在这个代码实现中,参数被命名为了`left`和`right`,代表`+`左边和右边的两个`Vector2D`对象。函数返回了一个新的`Vector2D`的对象,这个对象的`x`和`y`分别等于两个参数对象的`x`和`y`的和。 这个函数是全局的,而不是`Vector2D`结构的成员方法,所以任意两个`Vector2D`对象都可以使用这个中置运算符。 @@ -406,8 +403,7 @@ let afterIncrement = ++toIncrement // afterIncrement 现在也是 (4.0, 5.0) ``` ->注意: -> +>注意: 默认的赋值符是不可重载的。只有组合赋值符可以重载。三目条件运算符 `a?b:c` 也是不可重载。 ### 比较运算符 @@ -490,3 +486,4 @@ let plusMinusVector = firstVector +- secondVector ``` 这个运算符把两个向量的`x`相加,把向量的`y`相减。因为他实际是属于加减运算,所以让它保持了和加法一样的结合性和优先级(`left`和`140`)。查阅完整的Swift默认结合性和优先级的设置,请移步[表达式](../chapter3/04_Expressions.html); + From 9f58dfc4e6302d863f15141ab862157dcfe5bc46 Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 19:58:40 +0800 Subject: [PATCH 09/14] fix 3.1 about the language reference --- source/chapter3/01_About_the_Language_Reference.md | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/source/chapter3/01_About_the_Language_Reference.md b/source/chapter3/01_About_the_Language_Reference.md index d3a0cfb0..df686f68 100644 --- a/source/chapter3/01_About_the_Language_Reference.md +++ b/source/chapter3/01_About_the_Language_Reference.md @@ -1,5 +1,4 @@ -> 翻译:ChildhoodAndy - +> 翻译:ChildhoodAndy > 校对:numbbbbb @@ -27,17 +26,13 @@ Swift语言相对小点,这是由于在Swift代码中几乎无处不在的许 - 在少数情况下,常规字体文字用来描述语法产式规则的右边。 - 可选的句法范畴和文字用尾标`opt`来标记。 - 举个例子,getter-setter的语法块的定义如下: -> GRAMMAR OF A GETTER-SETTER BLOCK - +> GRAMMAR OF A GETTER-SETTER BLOCK > *getter-setter-block* → {­ [*getter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/getter-clause) [­*setter-clause*­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/setter-clause)*opt* ­}­ | {­ [*setter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/setter-clause) [­*getter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/getter-clause)­}­ 这个定义表明,一个getter-setter方法​​块可以由一个getter子句后跟一个可选的setter子句构成,用大括号括起来,或者由一个setter子句后跟一个getter子句构成,用大括号括起来。上述的文法产生等价于下面的两个产生,明确阐明如何二中择一: -> GRAMMAR OF A GETTER-SETTER BLOCK - -> getter-setter-block → {­ [*getter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/getter-clause) [*­setter-clause*­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/setter-clause)*opt* ­}­­ - +> GRAMMAR OF A GETTER-SETTER BLOCK +> getter-setter-block → {­ [*getter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/getter-clause) [*­setter-clause*­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/setter-clause)*opt* ­}­­ > getter-setter-block → {­ [*setter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/setter-clause) [*­getter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/getter-clause)­}­ From 0d9480fc95abf31b37eaa08df53b32c543f8c14d Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 20:13:44 +0800 Subject: [PATCH 10/14] fix 3.2 lexical structure --- source/chapter3/02_Lexical_Structure.md | 231 ++++++++---------------- 1 file changed, 78 insertions(+), 153 deletions(-) diff --git a/source/chapter3/02_Lexical_Structure.md b/source/chapter3/02_Lexical_Structure.md index e9e3b822..67febb0b 100644 --- a/source/chapter3/02_Lexical_Structure.md +++ b/source/chapter3/02_Lexical_Structure.md @@ -33,55 +33,31 @@ Swift 的“词法结构(*lexical structure*)”描述了如何在该语言 闭包(*closure*)中如果没有明确指定参数名称,参数将被隐式命名为 $0$1$2... 这些命名在闭包作用域内是合法的标识符。 -> 标识符语法 -> -> *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+00B2–U+00B5, 或 U+00B7–U+00BA -> -> *identifier-head* → U+00BC–U+00BE, U+00C0–U+00D6, U+00D8–U+00F6, 或 U+00F8–U+00FF -> -> *identifier-head* → U+0100–U+02FF, U+0370–U+167F, U+1681–U+180D, 或 U+180F–U+1DBF -> -> *identifier-head* → U+1E00–U+1FFF -> -> *identifier-head* → U+200B–U+200D, U+202A–U+202E, U+203F–U+2040, U+2054, 或 U+2060–U+206F -> -> *identifier-head* → U+2070–U+20CF, U+2100–U+218F, U+2460–U+24FF, 或 U+2776–U+2793 -> -> *identifier-head* → U+2C00–U+2DFF 或 U+2E80–U+2FFF -> -> *identifier-head* → U+3004–U+3007, U+3021–U+302F, U+3031–U+303F, 或 U+3040–U+D7FF -> -> *identifier-head* → U+F900–U+FD3D, U+FD40–U+FDCF, U+FDF0–U+FE1F, 或 U+FE30–U+FE44 -> -> *identifier-head* → U+FE47–U+FFFD -> -> *identifier-head* → U+10000–U+1FFFD, U+20000–U+2FFFD, U+30000–U+3FFFD, 或 U+40000–U+4FFFD -> -> *identifier-head* → U+50000–U+5FFFD, U+60000–U+6FFFD, U+70000–U+7FFFD, 或 U+80000–U+8FFFD -> -> *identifier-head* → U+90000–U+9FFFD, U+A0000–U+AFFFD, U+B0000–U+BFFFD, 或 U+C0000–U+CFFFD -> -> *identifier-head* → U+D0000–U+DFFFD 或 U+E0000–U+EFFFD -> -> *identifier-character* → 数字 0 到 9 -> -> *identifier-character* → U+0300–U+036F, U+1DC0–U+1DFF, U+20D0–U+20FF, or U+FE20–U+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) +> 标识符语法 +> *标识符* → [*标识符头(Head)*](LexicalStructure.html#identifier_head) [*标识符字符列表*](LexicalStructure.html#identifier_characters) _可选_ +> *标识符* → **`** [*标识符头(Head)*](LexicalStructure.html#identifier_head) [*标识符字符列表*](LexicalStructure.html#identifier_characters) _可选_ **`** +> *标识符* → [*隐式参数名*](LexicalStructure.html#implicit_parameter_name) +> *标识符列表* → [*标识符*](LexicalStructure.html#identifier) | [*标识符*](LexicalStructure.html#identifier) **,** [*标识符列表*](LexicalStructure.html#identifier_list) +> *标识符头(Head)* → Upper- or lowercase letter A through Z +> *标识符头(Head)* → U+00A8, U+00AA, U+00AD, U+00AF, U+00B2–U+00B5, or U+00B7–U+00BA +> *标识符头(Head)* → U+00BC–U+00BE, U+00C0–U+00D6, U+00D8–U+00F6, or U+00F8–U+00FF +> *标识符头(Head)* → U+0100–U+02FF, U+0370–U+167F, U+1681–U+180D, or U+180F–U+1DBF +> *标识符头(Head)* → U+1E00–U+1FFF +> *标识符头(Head)* → U+200B–U+200D, U+202A–U+202E, U+203F–U+2040, U+2054, or U+2060–U+206F +> *标识符头(Head)* → U+2070–U+20CF, U+2100–U+218F, U+2460–U+24FF, or U+2776–U+2793 +> *标识符头(Head)* → U+2C00–U+2DFF or U+2E80–U+2FFF +> *标识符头(Head)* → U+3004–U+3007, U+3021–U+302F, U+3031–U+303F, or U+3040–U+D7FF +> *标识符头(Head)* → U+F900–U+FD3D, U+FD40–U+FDCF, U+FDF0–U+FE1F, or U+FE30–U+FE44 +> *标识符头(Head)* → U+FE47–U+FFFD +> *标识符头(Head)* → U+10000–U+1FFFD, U+20000–U+2FFFD, U+30000–U+3FFFD, or U+40000–U+4FFFD +> *标识符头(Head)* → U+50000–U+5FFFD, U+60000–U+6FFFD, U+70000–U+7FFFD, or U+80000–U+8FFFD +> *标识符头(Head)* → U+90000–U+9FFFD, U+A0000–U+AFFFD, U+B0000–U+BFFFD, or U+C0000–U+CFFFD +> *标识符头(Head)* → U+D0000–U+DFFFD or U+E0000–U+EFFFD +> *标识符字符* → 数值 0 到 9 +> *标识符字符* → U+0300–U+036F, U+1DC0–U+1DFF, U+20D0–U+20FF, or U+FE20–U+FE2F +> *标识符字符* → [*标识符头(Head)*](LexicalStructure.html#identifier_head) +> *标识符字符列表* → [*标识符字符*](LexicalStructure.html#identifier_character) [*标识符字符列表*](LexicalStructure.html#identifier_characters) _可选_ +> *隐式参数名* → **$** [*十进制数字列表*](LexicalStructure.html#decimal_digits) ## 关键字 @@ -89,11 +65,8 @@ Swift 的“词法结构(*lexical structure*)”描述了如何在该语言 被保留的关键字(*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*,这些关键字在特定上下文之外可以被用于标识符。 @@ -107,9 +80,8 @@ Swift 的“词法结构(*lexical structure*)”描述了如何在该语言 "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) +> 字面量语法 +> *字面量* → [*整型字面量*](LexicalStructure.html#integer_literal) | [*浮点数字面量*](LexicalStructure.html#floating_point_literal) | [*字符串字面量*](LexicalStructure.html#string_literal) ### 整型字面量 @@ -128,49 +100,28 @@ Swift 的“词法结构(*lexical structure*)”描述了如何在该语言 除非特殊指定,整型字面量的默认类型为 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­* +> 整型字面量语法 +> *整型字面量* → [*二进制字面量*](LexicalStructure.html#binary_literal) +> *整型字面量* → [*八进制字面量*](LexicalStructure.html#octal_literal) +> *整型字面量* → [*十进制字面量*](LexicalStructure.html#decimal_literal) +> *整型字面量* → [*十六进制字面量*](LexicalStructure.html#hexadecimal_literal) +> *二进制字面量* → **0b** [*二进制数字*](LexicalStructure.html#binary_digit) [*二进制字面量字符列表*](LexicalStructure.html#binary_literal_characters) _可选_ +> *二进制数字* → 数值 0 到 1 +> *二进制字面量字符* → [*二进制数字*](LexicalStructure.html#binary_digit) | **_** +> *二进制字面量字符列表* → [*二进制字面量字符*](LexicalStructure.html#binary_literal_character) [*二进制字面量字符列表*](LexicalStructure.html#binary_literal_characters) _可选_ +> *八进制字面量* → **0o** [*八进字数字*](LexicalStructure.html#octal_digit) [*八进制字符列表*](LexicalStructure.html#octal_literal_characters) _可选_ +> *八进字数字* → 数值 0 到 7 +> *八进制字符* → [*八进字数字*](LexicalStructure.html#octal_digit) | **_** +> *八进制字符列表* → [*八进制字符*](LexicalStructure.html#octal_literal_character) [*八进制字符列表*](LexicalStructure.html#octal_literal_characters) _可选_ +> *十进制字面量* → [*十进制数字*](LexicalStructure.html#decimal_digit) [*十进制字符列表*](LexicalStructure.html#decimal_literal_characters) _可选_ +> *十进制数字* → 数值 0 到 9 +> *十进制数字列表* → [*十进制数字*](LexicalStructure.html#decimal_digit) [*十进制数字列表*](LexicalStructure.html#decimal_digits) _可选_ +> *十进制字符* → [*十进制数字*](LexicalStructure.html#decimal_digit) | **_** +> *十进制字符列表* → [*十进制字符*](LexicalStructure.html#decimal_literal_character) [*十进制字符列表*](LexicalStructure.html#decimal_literal_characters) _可选_ +> *十六进制字面量* → **0x** [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制字面量字符列表*](LexicalStructure.html#hexadecimal_literal_characters) _可选_ +> *十六进制数字* → 数值 0 到 9, a through f, or A through F +> *十六进制字符* → [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) | **_** +> *十六进制字面量字符列表* → [*十六进制字符*](LexicalStructure.html#hexadecimal_literal_character) [*十六进制字面量字符列表*](LexicalStructure.html#hexadecimal_literal_characters) _可选_ ### 浮点型字面量 @@ -193,33 +144,24 @@ Swift 的“词法结构(*lexical structure*)”描述了如何在该语言 除非特殊指定,浮点型字面量的默认类型为 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* → **+**­ | **-**­ - - +> 浮点型字面量语法 +> *浮点数字面量* → [*十进制字面量*](LexicalStructure.html#decimal_literal) [*十进制分数*](LexicalStructure.html#decimal_fraction) _可选_ [*十进制指数*](LexicalStructure.html#decimal_exponent) _可选_ +> *浮点数字面量* → [*十六进制字面量*](LexicalStructure.html#hexadecimal_literal) [*十六进制分数*](LexicalStructure.html#hexadecimal_fraction) _可选_ [*十六进制指数*](LexicalStructure.html#hexadecimal_exponent) +> *十进制分数* → **.** [*十进制字面量*](LexicalStructure.html#decimal_literal) +> *十进制指数* → [*浮点数e*](LexicalStructure.html#floating_point_e) [*正负号*](LexicalStructure.html#sign) _可选_ [*十进制字面量*](LexicalStructure.html#decimal_literal) +> *十六进制分数* → **.** [*十六进制字面量*](LexicalStructure.html#hexadecimal_literal) _可选_ +> *十六进制指数* → [*浮点数p*](LexicalStructure.html#floating_point_p) [*正负号*](LexicalStructure.html#sign) _可选_ [*十六进制字面量*](LexicalStructure.html#hexadecimal_literal) +> *浮点数e* → **e** | **E** +> *浮点数p* → **p** | **P** +> *正负号* → **+** | **-** ### 文本型字面量 文本型字面量(*string literal*)由双引号中的字符串组成,形式如下: - "characters" +```swift +"characters" +``` 文本型字面量中不能包含未转义的双引号 `"`、未转义的反斜线`\`、回车符(*carriage return*)或换行符(*line feed*)。 @@ -254,25 +196,16 @@ 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) +> 字符型字面量语法 +> *字符串字面量* → **"** [*引用文本*](LexicalStructure.html#quoted_text) **"** +> *引用文本* → [*引用文本条目*](LexicalStructure.html#quoted_text_item) [*引用文本*](LexicalStructure.html#quoted_text) _可选_ +> *引用文本条目* → [*转义字符*](LexicalStructure.html#escaped_character) +> *引用文本条目* → **\(** [*表达式*](..\chapter3\04_Expressions.html#expression) **)** +> *引用文本条目* → 除了"­, \­, U+000A, or U+000D的所有Unicode的字符 +> *转义字符* → **\0** | **\\** | **\t** | **\n** | **\r** | **\"** | **\'** +> *转义字符* → **\x** [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) +> *转义字符* → **\u** [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) +> *转义字符* → **\U** [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) ## 运算符 @@ -285,11 +218,8 @@ Swift 标准库定义了许多可供使用的运算符,其中大部分在 [基 运算符两侧的空白被用来区分该运算符是否为前缀运算符(*prefix operator*)、后缀运算符(*postfix operator*)或二元运算符(*binary operator*)。规则总结如下: * 如果运算符两侧都有空白或两侧都无空白,将被看作二元运算符。例如:`a+b` 和 `a + b` 中的运算符 `+` 被看作二元运算符。 - * 如果运算符只有左侧空白,将被看作前缀一元运算符。例如 `a ++b` 中的 `++` 被看作前缀一元运算符。 - * 如果运算符只有右侧空白,将被看作后缀一元运算符。例如 `a++ b` 中的 `++` 被看作后缀一元运算符。 - * 如果运算符左侧没有空白并紧跟 `.`,将被看作后缀一元运算符。例如 `a++.b` 中的 `++` 被看作后缀一元运算符(同理, `a++ . b` 中的 `++` 是后缀一元运算符而 `a ++ .b` 中的 `++` 不是). 鉴于这些规则,运算符前的字符 `(`、`[` 和 `{` ;运算符后的字符 `)`、`]` 和 `}` 以及字符 `,`、`;` 和 `:` 都将用于空白检测。 @@ -300,14 +230,9 @@ Swift 标准库定义了许多可供使用的运算符,其中大部分在 [基 要学习如何自定义新的运算符,请参考 [自定义操作符](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) +> 运算符语法语法 +> *运算符* → [*运算符字符*](LexicalStructure.html#operator_character) [*运算符*](LexicalStructure.html#operator) _可选_ +> *运算符字符* → **/** | **=** | **-** | **+** | **!** | ***** | **%** | **<** | **>** | **&** | **|** | **^** | **~** | **.** +> *二元运算符* → [*运算符*](LexicalStructure.html#operator) +> *前置运算符* → [*运算符*](LexicalStructure.html#operator) +> *后置运算符* → [*运算符*](LexicalStructure.html#operator) From 997f1ad82f8e81ba438a8aab8fa62c1af7a6cca5 Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 20:25:19 +0800 Subject: [PATCH 11/14] fix 3.3 types --- source/chapter3/03_Types.md | 125 ++++++++++--------- source/chapter3/09_Summary_of_the_Grammar.md | 2 +- 2 files changed, 68 insertions(+), 59 deletions(-) diff --git a/source/chapter3/03_Types.md b/source/chapter3/03_Types.md index ea2722c5..3bddee50 100644 --- a/source/chapter3/03_Types.md +++ b/source/chapter3/03_Types.md @@ -1,23 +1,22 @@ -> 翻译:lyuka - -> 校对:numbbbbb +> 翻译:lyuka +> 校对:numbbbbb, stanzhai # 类型(Types) ----------------- 本页包含内容: -- [类型注解(Type Annotation)](#type_annotation) -- [类型标识符(Type Identifier)](#type_identifier) -- [元组类型(Tuple Type)](#tuple_type) -- [函数类型(Function Type)](#function_type) -- [数组类型(Array Type)](#array_type) -- [可选类型(Optional Type)](#optional_type) -- [隐式解析可选类型(Implicitly Unwrapped Optional Type)](#implicitly_unwrapped_optional_type) -- [协议合成类型(Protocol Composition Type)](#protocol_composition_type) -- [元类型(Metatype Type)](#metatype_type) -- [类型继承子句(Type Inheritance Clause)](#type_inheritance_clause) -- [类型推断(Type Inference)](#type_inference) +- [类型注解(Type Annotation)](#type_annotation) +- [类型标识符(Type Identifier)](#type_identifier) +- [元组类型(Tuple Type)](#tuple_type) +- [函数类型(Function Type)](#function_type) +- [数组类型(Array Type)](#array_type) +- [可选类型(Optional Type)](#optional_type) +- [隐式解析可选类型(Implicitly Unwrapped Optional Type)](#implicitly_unwrapped_optional_type) +- [协议合成类型(Protocol Composition Type)](#protocol_composition_type) +- [元类型(Metatype Type)](#metatype_type) +- [类型继承子句(Type Inheritance Clause)](#type_inheritance_clause) +- [类型推断(Type Inference)](#type_inference) Swift 语言存在两种类型:命名型类型和复合型类型。*命名型类型*是指定义时可以给定名字的类型。命名型类型包括类、结构体、枚举和协议。比如,一个用户定义的类`MyClass`的实例拥有类型`MyClass`。除了用户定义的命名型类型,Swift 标准库也定义了很多常用的命名型类型,包括那些表示数组、字典和可选值的类型。 @@ -27,14 +26,14 @@ Swift 语言存在两种类型:命名型类型和复合型类型。*命名型 本节讨论 Swift 语言本身定义的类型,并描述 Swift 中的类型推断行为。 ->类型的语法: -*type* → *array-type* | *function-type* | *type-identifier* | *tuple-type* | *optional-type* | *implicitly-unwrapped-optional-type* | protocol-composition-type | metatype-type +> 类型语法 +> *类型* → [*数组类型*](..\chapter3\03_Types.html#array_type) | [*函数类型*](..\chapter3\03_Types.html#function_type) | [*类型标识*](..\chapter3\03_Types.html#type_identifier) | [*元组类型*](..\chapter3\03_Types.html#tuple_type) | [*可选类型*](..\chapter3\03_Types.html#optional_type) | [*隐式解析可选类型*](..\chapter3\03_Types.html#implicitly_unwrapped_optional_type) | [*协议合成类型*](..\chapter3\03_Types.html#protocol_composition_type) | [*元型类型*](..\chapter3\03_Types.html#metatype_type) ##类型注解 类型注解显式地指定一个变量或表达式的值。类型注解始于冒号`:`终于类型,比如下面两个例子: -```javascript +```swift let someTuple:(Double, Double) = (3.14159, 2.71828) func someFunction(a: Int){ /* ... */ } ``` @@ -42,31 +41,32 @@ func someFunction(a: Int){ /* ... */ } 类型注解可以在类型之前包含一个类型特性(type attributes)的可选列表。 ->类型注解的语法: -*type-annotation* → :*attributes*[opt] *type* +> 类型注解语法 +> *类型注解* → **:** [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type) ##类型标识符 + 类型标识符引用命名型类型或者是命名型/复合型类型的别名。 大多数情况下,类型标识符引用的是同名的命名型类型。例如类型标识符`Int`引用命名型类型`Int`,同样,类型标识符`Dictionary`引用命名型类型`Dictionary`。 在两种情况下类型标识符引用的不是同名的类型。情况一,类型标识符引用的是命名型/复合型类型的类型别名。比如,在下面的例子中,类型标识符使用`Point`来引用元组`(Int, Int)`: -```javascript +```swift typealias Point = (Int, Int) let origin: Point = (0, 0) ``` 情况二,类型标识符使用dot(`.`)语法来表示在其它模块(modules)或其它类型嵌套内声明的命名型类型。例如,下面例子中的类型标识符引用在`ExampleModule`模块中声明的命名型类型`MyType`: -```javascript +```swift var someValue: ExampleModule.MyType ``` ->类型标识符的语法: -*type-identifier* → *type-name generic-argument-clause*[opt] | *type-name generic-argument-clause*[opt].*type-identifier* -*type-name* → *identifier* +> 类型标识语法 +> *类型标识* → [*类型名称*](..\chapter3\03_Types.html#type_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ | [*类型名称*](..\chapter3\03_Types.html#type_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ **.** [*类型标识*](..\chapter3\03_Types.html#type_identifier) +> *类名* → [*标识符*](LexicalStructure.html#identifier) ##元组类型 @@ -76,24 +76,25 @@ var someValue: ExampleModule.MyType `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* +> 元组类型语法 +> *元组类型* → **(** [*元组类型主体*](..\chapter3\03_Types.html#tuple_type_body) _可选_ **)** +> *元组类型主体* → [*元组类型的元素列表*](..\chapter3\03_Types.html#tuple_type_element_list) **...** _可选_ +> *元组类型的元素列表* → [*元组类型的元素*](..\chapter3\03_Types.html#tuple_type_element) | [*元组类型的元素*](..\chapter3\03_Types.html#tuple_type_element) **,** [*元组类型的元素列表*](..\chapter3\03_Types.html#tuple_type_element_list) +> *元组类型的元素* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **inout** _可选_ [*类型*](..\chapter3\03_Types.html#type) | **inout** _可选_ [*元素名*](..\chapter3\03_Types.html#element_name) [*类型注解*](..\chapter3\03_Types.html#type_annotation) +> *元素名* → [*标识符*](LexicalStructure.html#identifier) ##函数类型 + 函数类型表示一个函数、方法或闭包的类型,它由一个参数类型和返回值类型组成,中间用箭头`->`隔开: -- `parameter type` -> `return type` +- `parameter type` -> `return type` 由于 *参数类型* 和 *返回值类型* 可以是元组类型,所以函数类型可以让函数与方法支持多参数与多返回值。 你可以对函数类型应用带有参数类型`()`并返回表达式类型的`auto_closure`属性(见类型属性章节)。一个自动闭包函数捕获特定表达式上的隐式闭包而非表达式本身。下面的例子使用`auto_closure`属性来定义一个很简单的assert函数: -```javascript +```swift func simpleAssert(condition: @auto_closure () -> Bool, message: String){ if !condition(){ println(message) @@ -109,15 +110,16 @@ simpleAssert(testNumber % 2 == 0, "testNumber isn't an even number.") 柯里化函数(curried function)的类型相当于一个嵌套函数类型。例如,下面的柯里化函数`addTwoNumber()()`的类型是`Int -> Int -> Int`: -```javascript +```swift 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 +```swift func addTwoNumbers(a: Int) -> (Int -> Int){ func addTheSecondNumber(b: Int) -> Int{ return a + b @@ -126,14 +128,16 @@ func addTwoNumbers(a: Int) -> (Int -> Int){ } addTwoNumbers(4)(5) // Returns 9 ``` ->函数类型的语法: -*function-type* → *type* **->** *type* + +> 函数类型语法 +> *函数类型* → [*类型*](..\chapter3\03_Types.html#type) **->** [*类型*](..\chapter3\03_Types.html#type) ##数组类型 + Swift语言使用类型名紧接中括号`[]`来简化标准库中定义的命名型类型`Array`。换句话说,下面两个声明是等价的: -```javascript +```swift let someArray: String[] = ["Alex", "Brian", "Dave"] let someArray: Array = ["Alex", "Brian", "Dave"] ``` @@ -141,26 +145,27 @@ let someArray: Array = ["Alex", "Brian", "Dave"] 上面的例子同时显示,你可以使用`[]`作为初始值构造数组,空的`[]`则用来来构造指定类型的空数组。 -```javascript +```swift var emptyArray: Double[] = [] ``` 你也可以使用链接起来的多个`[]`集合来构造多维数组。例如,下例使用三个`[]`集合来构造三维整型数组: -```javascript +```swift 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*`[ ]` +> 数组类型语法 +> *数组类型* → [*类型*](..\chapter3\03_Types.html#type) **[** **]** | [*数组类型*](..\chapter3\03_Types.html#array_type) **[** **]** ##可选类型 + Swift定义后缀`?`来作为标准库中的定义的命名型类型`Optional`的简写。换句话说,下面两个声明是等价的: -```javascript +```swift var optionalInteger: Int? var optionalInteger: Optional ``` @@ -174,7 +179,7 @@ var optionalInteger: Optional 如果一个可选类型的实例包含一个值,那么你就可以使用后缀操作符`!`来获取该值,正如下面描述的: -```javascript +```swift optionalInteger = 42 optionalInteger! // 42 ``` @@ -184,14 +189,15 @@ optionalInteger! // 42 更多细节以及更多如何使用可选类型的例子,见章节“可选”。 ->可选类型语法: -*optional-type* → *type*? +> 可选类型语法 +> *可选类型* → [*类型*](..\chapter3\03_Types.html#type) **?** ##隐式解析可选类型 + Swift语言定义后缀`!`作为标准库中命名类型`ImplicitlyUnwrappedOptional`的简写。换句话说,下面两个声明等价: -```javascript +```swift var implicitlyUnwrappedString: String! var implicitlyUnwrappedString: ImplicitlyUnwrappedOptional ``` @@ -207,35 +213,38 @@ var implicitlyUnwrappedString: ImplicitlyUnwrappedOptional 关于隐式解析可选的更多细节,见章节“隐式解析可选”。 ->隐式解析可选的语法: -implicitly-unwrapped-optional-type → type! +> 隐式解析可选类型(Implicitly Unwrapped Optional Type)语法 +> *隐式解析可选类型* → [*类型*](..\chapter3\03_Types.html#type) **!** ##协议合成类型 协议合成类型是一种符合每个协议的指定协议列表类型。协议合成类型可能会用在类型注解和泛型参数中。 协议合成类型的形式如下: -```javascript + +```swift protocol ``` + 协议合成类型允许你指定一个值,其类型可以适配多个协议的条件,而且不需要定义一个新的命名型协议来继承其它想要适配的各个协议。比如,协议合成类型`protocol`等效于一个从`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* +> 协议合成类型语法 +> *协议合成类型* → **protocol** **<** [*协议标识符列表*](..\chapter3\03_Types.html#protocol_identifier_list) _可选_ **>** +> *协议标识符列表* → [*协议标识符*](..\chapter3\03_Types.html#protocol_identifier) | [*协议标识符*](..\chapter3\03_Types.html#protocol_identifier) **,** [*协议标识符列表*](..\chapter3\03_Types.html#protocol_identifier_list) +> *协议标识符* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) ##元类型 + 元类型是指所有类型的类型,包括类、结构体、枚举和协议。 类、结构体或枚举类型的元类型是相应的类型名紧跟`.Type`。协议类型的元类型——并不是运行时适配该协议的具体类型——是该协议名字紧跟`.Protocol`。比如,类`SomeClass`的元类型就是`SomeClass.Type`,协议`SomeProtocol`的元类型就是`SomeProtocal.Protocol`。 你可以使用后缀`self`表达式来获取类型。比如,`SomeClass.self`返回`SomeClass`本身,而不是`SomeClass`的一个实例。同样,`SomeProtocol.self`返回`SomeProtocol`本身,而不是运行时适配`SomeProtocol`的某个类型的实例。还可以对类型的实例使用`dynamicType`表达式来获取该实例在运行阶段的类型,如下所示: -```javascript +```swift class SomeBaseClass { class func printClassName() { println("SomeBaseClass") @@ -266,19 +275,19 @@ someInstance.dynamicType.printClassName() 枚举定义中的类型继承子句可以是一个协议列表,或是指定原始值的枚举,一个单独的指定原始值类型的命名型类型。使用类型继承子句来指定原始值类型的枚举定义的例子,见章节“原始值”。 ->类型继承子句的语法: -*type-inheritance-clause* → :*type-inheritance-list* -*type-inheritance-list* → *type-identifier* | *type-identifier*, *type-inheritance-list* +> 元型(Metatype)类型语法 +> *元型类型* → [*类型*](..\chapter3\03_Types.html#type) **.** **Type** | [*类型*](..\chapter3\03_Types.html#type) **.** **Protocol** ##类型推断 + Swift广泛的使用类型推断,从而允许你可以忽略很多变量和表达式的类型或部分类型。比如,对于`var x: Int = 0`,你可以完全忽略类型而简写成`var x = 0`——编译器会正确的推断出`x`的类型`Int`。类似的,当完整的类型可以从上下文推断出来时,你也可以忽略类型的一部分。比如,如果你写了`let dict: Dictionary = ["A": 1]`,编译提也能推断出`dict`的类型是`Dictionary`。 在上面的两个例子中,类型信息从表达式树(expression tree)的叶子节点传向根节点。也就是说,`var x: Int = 0`中`x`的类型首先根据`0`的类型进行推断,然后将该类型信息传递到根节点(变量`x`)。 在Swift中,类型信息也可以反方向流动——从根节点传向叶子节点。在下面的例子中,常量`eFloat`上的显式类型注解(`:Float`)导致数字字面量`2.71828`的类型是`Float`而非`Double`。 -```javascript +```swift let e = 2.71828 // The type of e is inferred to be Double. let eFloat: Float = 2.71828 // The type of eFloat is Float. ``` diff --git a/source/chapter3/09_Summary_of_the_Grammar.md b/source/chapter3/09_Summary_of_the_Grammar.md index 37a2f41a..778e7dd7 100644 --- a/source/chapter3/09_Summary_of_the_Grammar.md +++ b/source/chapter3/09_Summary_of_the_Grammar.md @@ -687,7 +687,7 @@ _________________

-> 类型标注语法 +> 类型注解语法 > *类型注解* → **:** [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type)

From 1045cccfce9f16e3fcf3c191389b8176d1e2e183 Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 20:29:50 +0800 Subject: [PATCH 12/14] fix 3.3 types(2) --- source/chapter3/03_Types.md | 10 ++++++---- source/chapter3/09_Summary_of_the_Grammar.md | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/source/chapter3/03_Types.md b/source/chapter3/03_Types.md index 3bddee50..32f971fc 100644 --- a/source/chapter3/03_Types.md +++ b/source/chapter3/03_Types.md @@ -262,11 +262,12 @@ someInstance.dynamicType.printClassName() // prints "SomeSubClass ``` ->元类型的语法: -*metatype-type* → *type*.**Type** | *type*.**Protocol** +> 元(Metatype)类型语法 +> *元类型* → [*类型*](..\chapter3\03_Types.html#type) **.** **Type** | [*类型*](..\chapter3\03_Types.html#type) **.** **Protocol** x ##类型继承子句 + 类型继承子句被用来指定一个命名型类型继承哪个类且适配哪些协议。类型继承子句开始于冒号`:`,紧跟由`,`隔开的类型标识符列表。 类可以继承单个超类,适配任意数量的协议。当定义一个类时,超类的名字必须出现在类型标识符列表首位,然后跟上该类需要适配的任意数量的协议。如果一个类不是从其它类继承而来,那么列表可以以协议开头。关于类继承更多的讨论和例子,见章节“继承”。 @@ -275,8 +276,9 @@ someInstance.dynamicType.printClassName() 枚举定义中的类型继承子句可以是一个协议列表,或是指定原始值的枚举,一个单独的指定原始值类型的命名型类型。使用类型继承子句来指定原始值类型的枚举定义的例子,见章节“原始值”。 -> 元型(Metatype)类型语法 -> *元型类型* → [*类型*](..\chapter3\03_Types.html#type) **.** **Type** | [*类型*](..\chapter3\03_Types.html#type) **.** **Protocol** +> 类型继承子句语法 +> *类型继承子句* → **:** [*类型继承列表*](..\chapter3\03_Types.html#type_inheritance_list) +> *类型继承列表* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) | [*类型标识*](..\chapter3\03_Types.html#type_identifier) **,** [*类型继承列表*](..\chapter3\03_Types.html#type_inheritance_list) ##类型推断 diff --git a/source/chapter3/09_Summary_of_the_Grammar.md b/source/chapter3/09_Summary_of_the_Grammar.md index 778e7dd7..f301ddc4 100644 --- a/source/chapter3/09_Summary_of_the_Grammar.md +++ b/source/chapter3/09_Summary_of_the_Grammar.md @@ -734,8 +734,8 @@ _________________

-> 元型(Metatype)类型语法 -> *元型类型* → [*类型*](..\chapter3\03_Types.html#type) **.** **Type** | [*类型*](..\chapter3\03_Types.html#type) **.** **Protocol** +> 元(Metatype)类型语法 +> *元类型* → [*类型*](..\chapter3\03_Types.html#type) **.** **Type** | [*类型*](..\chapter3\03_Types.html#type) **.** **Protocol**

From a7c0f6f3d622530f96170b36f4b71364ad1da107 Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 20:59:23 +0800 Subject: [PATCH 13/14] fix 3.4 expressions --- source/chapter3/04_Expressions.md | 296 +++++++++---------- source/chapter3/09_Summary_of_the_Grammar.md | 162 +++++----- 2 files changed, 217 insertions(+), 241 deletions(-) diff --git a/source/chapter3/04_Expressions.md b/source/chapter3/04_Expressions.md index 53db2650..8cb26230 100644 --- a/source/chapter3/04_Expressions.md +++ b/source/chapter3/04_Expressions.md @@ -1,6 +1,5 @@ -> 翻译:sg552 - -> 校对:numbbbbb +> 翻译:sg552 +> 校对:numbbbbb, stanzhai # 表达式(Expressions) ----------------- @@ -19,10 +18,9 @@ Swift 中存在四种表达式: 前缀(prefix)表达式,二元(binary 前缀表达式和二元表达式就是对某些表达式使用各种运算符(operators)。 主要表达式是最短小的表达式,它提供了获取(变量的)值的一种途径。 后缀表达式则允许你建立复杂的表达式,例如配合函数调用和成员访问。 每种表达式都在下面有详细论述~ -> 表达式的语法 -> -> *expression* → *prefix-expression*­*binary-expressions(*opt) -> *expression-list* → *expression*­| *expression*­,­*expression-list* +> 表达式语法 +> *表达式* → [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) [*二元表达式列表*](..\chapter3\04_Expressions.html#binary_expressions) _可选_ +> *表达式列表* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*表达式*](..\chapter3\04_Expressions.html#expression) **,** [*表达式列表*](..\chapter3\04_Expressions.html#expression_list) ## 前缀表达式(Prefix Expressions) @@ -42,18 +40,17 @@ Swift 标准库支持如下的前缀操作符: 作为对上面标准库运算符的补充,你也可以对 某个函数的参数使用 '&'运算符。 更多信息,请参见: "In-Out parameters". -> 前缀表达式的语法 -> -> *prefix-expression* → *prefix-operator* (opt) *postfix-expression* -> *prefix-expression* → *in-out-expression*­ -> *in-out-expression* → &­*identifier*­ +> 前置表达式语法 +> *前置表达式* → [*前置运算符*](LexicalStructure.html#prefix_operator) _可选_ [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) +> *前置表达式* → [*写入写出(in-out)表达式*](..\chapter3\04_Expressions.html#in_out_expression) +> *写入写出(in-out)表达式* → **&** [*标识符*](LexicalStructure.html#identifier) ## 二元表达式(Binary Expressions) 二元表达式由 "左边参数" + "二元运算符" + "右边参数" 组成, 它有如下的形式: - `left-hand argument` `operator` `right-hand argument` +> `left-hand argument` `operator` `right-hand argument` Swift 标准库提供了如下的二元运算符: @@ -114,17 +111,18 @@ Swift 标准库提供了如下的二元运算符: 关于这些运算符(operators)的更多信息,请参见:Basic Operators and Advanced Operators. ->> 注意 ->> ->> 在解析时, 一个二元表达式表示为一个一级数组(a flat list), 这个数组(List)根据运算符的先后顺序,被转换成了一个tree. 例如: 2 + 3 * 5 首先被认为是: 2, + , `` 3``, *, 5. 随后它被转换成 tree (2 + (3 * 5)) +> 注意 +> 在解析时, 一个二元表达式表示为一个一级数组(a flat list), 这个数组(List)根据运算符的先后顺序,被转换成了一个tree. 例如: 2 + 3 * 5 首先被认为是: 2, + , `` 3``, *, 5. 随后它被转换成 tree (2 + (3 * 5)) + +

+ +> 二元表达式语法 +> *二元表达式* → [*二元运算符*](LexicalStructure.html#binary_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) +> *二元表达式* → [*赋值运算符*](..\chapter3\04_Expressions.html#assignment_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) +> *二元表达式* → [*条件运算符*](..\chapter3\04_Expressions.html#conditional_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) +> *二元表达式* → [*类型转换运算符*](..\chapter3\04_Expressions.html#type_casting_operator) +> *二元表达式列表* → [*二元表达式*](..\chapter3\04_Expressions.html#binary_expression) [*二元表达式列表*](..\chapter3\04_Expressions.html#binary_expressions) _可选_ -> 二元表达式的语法 -> -> *binary-expression* → *binary-operator*­*prefix-expression*­ -> *binary-expression* → *assignment-operator*­prefix-expression* -> *binary-expression* → *conditional-operator*­prefix-expression* -> *binary-expression* → *type-casting-operator*­ -> *binary-expression*s → *binary-expression*­*binary-expressions*(opt) ## 赋值表达式(Assignment Operator) @@ -132,7 +130,7 @@ Swift 标准库提供了如下的二元运算符: The assigment operator sets a new value for a given expression. It has the following form: 赋值表达式会对某个给定的表达式赋值。 它有如下的形式; -`expression` = `value` +> `expression` = `value` 就是把右边的 *value* 赋值给左边的 *expression*. 如果左边的*expression* 需要接收多个参数(是一个tuple ),那么右边必须也是一个具有同样数量参数的tuple. (允许嵌套的tuple) @@ -143,40 +141,36 @@ The assigment operator sets a new value for a given expression. It has the follo 赋值运算符不返回任何值。 -> 赋值表达式的语法 -> -> *assignment-operator* → =­ +> 赋值运算符语法 +> *赋值运算符* → **=** ## 三元条件运算符(Ternary Conditional Operator) 三元条件运算符 是根据条件来获取值。 形式如下: - `condition` ? `expression used if true` : `expression used if false` +> `condition` ? `expression used if true` : `expression used if false` 如果 `condition` 是true, 那么返回 第一个表达式的值(此时不会调用第二个表达式), 否则返回第二个表达式的值(此时不会调用第一个表达式)。 想看三元条件运算符的例子,请参见: Ternary Conditional Operator. -> 三元条件表达式 -> -> `conditional-operator` → ?­`expression`­:­ +> 三元条件运算符语法 +> *三元条件运算符* → **?** [*表达式*](..\chapter3\04_Expressions.html#expression) **:** ## 类型转换运算符(Type-Casting Operators) 有两种类型转换操作符: as 和 is. 它们有如下的形式: - `expression` as `type` - `expression` as? `type` - `expression` is `type` +> `expression` as `type` +> `expression` as? `type` +> `expression` is `type` as 运算符会把`目标表达式`转换成指定的`类型`(specified type),过程如下: - 如果类型转换成功, 那么目标表达式就会返回指定类型的实例(instance). 例如:把子类(subclass)变成父类(superclass)时. - - 如果转换失败,则会抛出编译错误( compile-time error)。 - - 如果上述两个情况都不是(也就是说,编译器在编译时期无法确定转换能否成功,) 那么目标表达式就会变成指定的类型的optional. (is an optional of the specified type ) 然后在运行时,如果转换成功, 目标表达式就会作为 optional的一部分来返回, 否则,目标表达式返回nil. 对应的例子是: 把一个 superclass 转换成一个 subclass. ```swift @@ -209,25 +203,23 @@ The check must not be known to be true or false at compile time. The following a 关于类型转换的更多内容和例子,请参见: Type Casting. -> 类型转换的语法 -> -> *type-casting-operator* → is­*type*­| as­?(opt)­*type* +> 类型转换运算符(type-casting-operator)语法 +> *类型转换运算符* → **is** [*类型*](..\chapter3\03_Types.html#type) | **as** **?** _可选_ [*类型*](..\chapter3\03_Types.html#type) -## 主要表达式(Primary Expressions) +## 主表达式(Primary Expressions) -`主要表达式`是最基本的表达式。 它们可以跟 前缀表达式,二元表达式,后缀表达式以及其他主要表达式组合使用。 +`主表达式`是最基本的表达式。 它们可以跟 前缀表达式,二元表达式,后缀表达式以及其他主要表达式组合使用。 -> 主要表达式的语法 -> -> *primary-expression* → *identifier*­*generic-argument-clause*(opt) -> *primary-expression* → *literal-expression*­ -> *primary-expression* → *self-expression*­ -> *primary-expression* → *superclass-expression*­ -> *primary-expression* → *closure-expression*­ -> *primary-expression* → *parenthesized-expression*­ -> *primary-expression* → *implicit-member-expression* -> *primary-expression* → *wildcard-expression* +> 主表达式语法 +> *主表达式* → [*标识符*](LexicalStructure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ +> *主表达式* → [*字面量表达式*](..\chapter3\04_Expressions.html#literal_expression) +> *主表达式* → [*self表达式*](..\chapter3\04_Expressions.html#self_expression) +> *主表达式* → [*超类表达式*](..\chapter3\04_Expressions.html#superclass_expression) +> *主表达式* → [*闭包表达式*](..\chapter3\04_Expressions.html#closure_expression) +> *主表达式* → [*圆括号表达式*](..\chapter3\04_Expressions.html#parenthesized_expression) +> *主表达式* → [*隐式成员表达式*](..\chapter3\04_Expressions.html#implicit_member_expression) +> *主表达式* → [*通配符表达式*](..\chapter3\04_Expressions.html#wildcard_expression) ### 字符型表达式(Literal Expression) @@ -244,37 +236,36 @@ The check must not be known to be true or false at compile time. The following a 一个array literal,是一个有序的值的集合。 它的形式是: - [`value 1`, `value 2`, `...`] +> [`value 1`, `value 2`, `...`] 数组中的最后一个表达式可以紧跟一个逗号(','). []表示空数组 。 array literal的type是 T[], 这个T就是数组中元素的type. 如果该数组中有多种type, T则是跟这些type的公共supertype最接近的type.(closest common supertype) 一个`dictionary literal` 是一个包含无序的键值对(key-value pairs)的集合,它的形式是: - [`key 1`: `value 1`, `key 2`: `value 2`, `...`] +> [`key 1`: `value 1`, `key 2`: `value 2`, `...`] dictionary 的最后一个表达式可以是一个逗号(','). [:] 表示一个空的dictionary. 它的type是 Dictionary (这里KeyType表示 key的type, ValueType表示 value的type) 如果这个dictionary 中包含多种 types, 那么KeyType, Value 则对应着它们的公共supertype最接近的type( closest common supertype). -> 字符型表达式的语法 -> -> *literal-expression* → *literal* -> *literal-expression* → *array-literal*­| *dictionary-literal*­ -> *literal-expression* → *\__FILE__*­| *\__LINE__*­| *\__COLUMN__*­| *\__FUNCTION__*­ -> *array-literal* → [­*array-literal-items*­opt­]­ -> *array-literal-items* → *array-literal-item*­,­(opt) | ­*array-literal-item*­,­*array-literal-items*­ -> *array-literal-item* → *expression*­ -> *dictionary-literal* → [­*dictionary-literal-items*­]­ [­:­]­ -> *dictionary-literal-items* → *dictionary-literal-item*,­(opt)­| *dictionary-literal-item*­,­*dictionary-literal-items*­ -> *dictionary-literal-item* → *expression*­:­*expression*­ +> 字面量表达式语法 +> *字面量表达式* → [*字面量*](LexicalStructure.html#literal) +> *字面量表达式* → [*数组字面量*](..\chapter3\04_Expressions.html#array_literal) | [*字典字面量*](..\chapter3\04_Expressions.html#dictionary_literal) +> *字面量表达式* → **__FILE__** | **__LINE__** | **__COLUMN__** | **__FUNCTION__** +> *数组字面量* → **[** [*数组字面量项列表*](..\chapter3\04_Expressions.html#array_literal_items) _可选_ **]** +> *数组字面量项列表* → [*数组字面量项*](..\chapter3\04_Expressions.html#array_literal_item) **,** _可选_ | [*数组字面量项*](..\chapter3\04_Expressions.html#array_literal_item) **,** [*数组字面量项列表*](..\chapter3\04_Expressions.html#array_literal_items) +> *数组字面量项* → [*表达式*](..\chapter3\04_Expressions.html#expression) +> *字典字面量* → **[** [*字典字面量项列表*](..\chapter3\04_Expressions.html#dictionary_literal_items) **]** | **[** **:** **]** +> *字典字面量项列表* → [*字典字面量项*](..\chapter3\04_Expressions.html#dictionary_literal_item) **,** _可选_ | [*字典字面量项*](..\chapter3\04_Expressions.html#dictionary_literal_item) **,** [*字典字面量项列表*](..\chapter3\04_Expressions.html#dictionary_literal_items) +> *字典字面量项* → [*表达式*](..\chapter3\04_Expressions.html#expression) **:** [*表达式*](..\chapter3\04_Expressions.html#expression) ### self表达式(Self Expression) self表达式是对 当前type 或者当前instance的引用。它的形式如下: -> self -> self.`member name` -> self[`subscript index`] -> self(`initializer arguments`) -> self.init(`initializer arguments`) +> self +> self.`member name` +> self[`subscript index`] +> self(`initializer arguments`) +> self.init(`initializer arguments`) 如果在 initializer, subscript, instance method中,self等同于当前type的instance. 在一个静态方法(static method), 类方法(class method)中, self等同于当前的type. @@ -301,40 +292,38 @@ struct Point { } ``` -> self表达式的语法 -> -> *self-expression* → self­ -> *self-expression* → self­.­*identifier*­ -> *self-expression* → self­[­*expression*­]­ -> *self-expression* → self­.­init­ +> Self 表达式语法 +> *self表达式* → **self** +> *self表达式* → **self** **.** [*标识符*](LexicalStructure.html#identifier) +> *self表达式* → **self** **[** [*表达式*](..\chapter3\04_Expressions.html#expression) **]** +> *self表达式* → **self** **.** **init** ### 超类表达式(Superclass Expression) 超类表达式可以使我们在某个class中访问它的超类. 它有如下形式: - super.`member name` - super[`subscript index`] - super.init(`initializer arguments`) +> super.`member name` +> super[`subscript index`] +> super.init(`initializer arguments`) 形式1 用来访问超类的某个成员(member). 形式2 用来访问该超类的 subscript 实现。 形式3 用来访问该超类的 initializer. 子类(subclass)可以通过超类(superclass)表达式在它们的 member, subscripting 和 initializers 中来利用它们超类中的某些实现(既有的方法或者逻辑)。 -> GRAMMAR OF A SUPERCLASS EXPRESSION - -> *superclass-expression* → *superclass-method-expression* | *superclass-subscript-expression*­| *superclass-initializer-expression* -> *superclass-method-expression* → super­.­*identifier* -> *superclass-subscript-expression* → super­[­*expression*­]­ -> *superclass-initializer-expression* → super­.­init­ +> 超类(superclass)表达式语法 +> *超类表达式* → [*超类方法表达式*](..\chapter3\04_Expressions.html#superclass_method_expression) | [*超类下标表达式*](..\chapter3\04_Expressions.html#超类下标表达式) | [*超类构造器表达式*](..\chapter3\04_Expressions.html#superclass_initializer_expression) +> *超类方法表达式* → **super** **.** [*标识符*](LexicalStructure.html#identifier) +> *超类下标表达式* → **super** **[** [*表达式*](..\chapter3\04_Expressions.html#expression) **]** +> *超类构造器表达式* → **super** **.** **init** ### 闭包表达式(Closure Expression) 闭包(closure) 表达式可以建立一个闭包(在其他语言中也叫 lambda, 或者 匿名函数(anonymous function)). 跟函数(function)的声明一样, 闭包(closure)包含了可执行的代码(跟方法主体(statement)类似) 以及接收(capture)的参数。 它的形式如下: ```swift - { (parameters) -> return type in - statements - } +{ (parameters) -> return type in + statements +} ``` 闭包的参数声明形式跟方法中的声明一样, 请参见:Function Declaration. @@ -384,22 +373,21 @@ myFunction { [weak parent = self.parent] in print(parent!.title) } 关于闭包表达式的更多信息和例子,请参见: Closure Expressions. -> 闭包表达式的语法 -> -> *closure-expression* → {­*closure-signature*­opt­*statements*­}­ -> *closure-signature* → *parameter-clause*­*function-result*­(opt)­in­ -> *closure-signature* → *identifier-list*­*function-result*­(opt)­in­ -> *closure-signature* → *capture-list*­*parameter-clause*­*function-result*­(opt)­in­ -> *closure-signature* → *capture-list*­*identifier-list*­*function-result*­(opt)­in­ -> *closure-signature* → *capture-list*­in­ -> *capture-list* → [­*capture-specifier*­*expression*­]­ -> *capture-specifier* → weak­| unowned­| unowned(safe)­| unowned(unsafe)­ +> 闭包表达式语法 +> *闭包表达式* → **{** [*闭包签名(Signational)*](..\chapter3\04_Expressions.html#closure_signature) _可选_ [*多条语句(Statements)*](..\chapter3\10_Statements.html#statements) **}** +> *闭包签名(Signational)* → [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** +> *闭包签名(Signational)* → [*标识符列表*](LexicalStructure.html#identifier_list) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** +> *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** +> *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) [*标识符列表*](LexicalStructure.html#identifier_list) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** +> *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) **in** +> *捕获(Capature)列表* → **[** [*捕获(Capature)说明符*](..\chapter3\04_Expressions.html#capture_specifier) [*表达式*](..\chapter3\04_Expressions.html#expression) **]** +> *捕获(Capature)说明符* → **weak** | **unowned** | **unowned(safe)** | **unowned(unsafe)** ### 隐式成员表达式(Implicit Member Expression) 在可以判断出类型(type)的上下文(context)中,隐式成员表达式是访问某个type的member( 例如 class method, enumeration case) 的简洁方法。 它的形式是: -.`member name` +> .`member name` 例子: @@ -408,23 +396,21 @@ var x = MyEnumeration.SomeValue x = .AnotherValue ``` -> 隐式成员表达式的语法 -> -> *implicit-member-expression* → .­*identifier* +> 隐式成员表达式语法 +> *隐式成员表达式* → **.** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) ### 圆括号表达式(Parenthesized Expression) 圆括号表达式由多个子表达式和逗号','组成。 每个子表达式前面可以有 identifier x: 这样的可选前缀。形式如下: -(`identifier 1`: `expression 1`, `identifier 2`: `expression 2`, `...`) +>(`identifier 1`: `expression 1`, `identifier 2`: `expression 2`, `...`) 圆括号表达式用来建立tuples , 然后把它做为参数传递给 function. 如果某个圆括号表达式中只有一个 子表达式,那么它的type就是 子表达式的type。例如: (1)的 type是Int, 而不是(Int) -> 圆括号表达式的语法 -> -> *parenthesized-expression* → (­*expression-element-list* (opt)­)­ -> *expression-element-list* → *expression-element*­| *expression-element*­,­*expression-element-list*­ -> *expression-element* → *expression*­| *identifier*­:­*expression* +> 圆括号表达式(Parenthesized Expression)语法 +> *圆括号表达式* → **(** [*表达式元素列表*](..\chapter3\04_Expressions.html#expression_element_list) _可选_ **)** +> *表达式元素列表* → [*表达式元素*](..\chapter3\04_Expressions.html#expression_element) | [*表达式元素*](..\chapter3\04_Expressions.html#expression_element) **,** [*表达式元素列表*](..\chapter3\04_Expressions.html#expression_element_list) +> *表达式元素* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) **:** [*表达式*](..\chapter3\04_Expressions.html#expression) ### 通配符表达式(Wildcard Expression) @@ -435,9 +421,8 @@ x = .AnotherValue // x is 10, 20 is ignored ``` -> 通配符表达式的语法 -> -> *wildcard-expression* → _­ +> 通配符表达式语法 +> *通配符表达式* → **_** ## 后缀表达式(Postfix Expressions) @@ -451,31 +436,30 @@ Swift 标准库提供了下列后缀表达式: 对于这些操作符的使用,请参见: Basic Operators and Advanced Operators -> 后缀表达式的语法 -> -> *postfix-expression* → *primary-expression* -> *postfix-expression* → *postfix-expression*­*postfix-operator* -> *postfix-expression* → *function-call-expression*­ -> *postfix-expression* → *initializer-expression*­ -> *postfix-expression* → *explicit-member-expression*­ -> *postfix-expression* → *postfix-self-expression*­ -> *postfix-expression* → *dynamic-type-expression*­ -> *postfix-expression* → *subscript-expression*­ -> *postfix-expression* → *forced-value-expression*­ -> *postfix-expression* → *optional-chaining-expression*­ +> 后置表达式语法 +> *后置表达式* → [*主表达式*](..\chapter3\04_Expressions.html#primary_expression) +> *后置表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) [*后置运算符*](..\chapter3\02_Lexical_Structure.html#postfix_operator) +> *后置表达式* → [*函数调用表达式*](..\chapter3\04_Expressions.html#function_call_expression) +> *后置表达式* → [*构造器表达式*](..\chapter3\04_Expressions.html#initializer_expression) +> *后置表达式* → [*显示成员表达式*](..\chapter3\04_Expressions.html#explicit_member_expression) +> *后置表达式* → [*后置self表达式*](..\chapter3\04_Expressions.html#postfix_self_expression) +> *后置表达式* → [*动态类型表达式*](..\chapter3\04_Expressions.html#dynamic_type_expression) +> *后置表达式* → [*下标表达式*](..\chapter3\04_Expressions.html#subscript_expression) +> *后置表达式* → [*强制取值(Forced Value)表达式*](..\chapter3\04_Expressions.html#forced_value_expression) +> *后置表达式* → [*可选链(Optional Chaining)表达式*](..\chapter3\04_Expressions.html#optional_chaining_expression) ### 函数调用表达式(Function Call Expression) 函数调用表达式由函数名和参数列表组成。它的形式如下: -`function name`(`argument value 1`, `argument value 2`) +> `function name`(`argument value 1`, `argument value 2`) The function name can be any expression whose value is of a function type. (不用翻译了, 太罗嗦) 如果该function 的声明中指定了参数的名字,那么在调用的时候也必须得写出来. 例如: -`function name`(`argument name 1`: `argument value 1`, `argument name 2`: `argument value 2`) +> `function name`(`argument name 1`: `argument value 1`, `argument name 2`: `argument value 2`) 可以在 函数调用表达式的尾部(最后一个参数之后)加上 一个闭包(closure) , 该闭包会被目标函数理解并执行。它具有如下两种写法: @@ -493,24 +477,23 @@ myData.someMethod() {$0 == 13} myData.someMethod {$0 == 13} ``` -> GRAMMAR OF A FUNCTION CALL EXPRESSION -> -> *function-call-expression* → *postfix-expression*­*parenthesized-expression* -> *function-call-expression* → *postfix-expression*­*parenthesized-expression*­(opt)­*trailing-closure*­ -> *trailing-closure* → *closure-expression*­ +> 函数调用表达式语法 +> *函数调用表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) [*圆括号表达式*](..\chapter3\04_Expressions.html#parenthesized_expression) +> *函数调用表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) [*圆括号表达式*](..\chapter3\04_Expressions.html#parenthesized_expression) _可选_ [*后置闭包(Trailing Closure)*](..\chapter3\04_Expressions.html#trailing_closure) +> *后置闭包(Trailing Closure)* → [*闭包表达式*](..\chapter3\04_Expressions.html#closure_expression) ### 初始化函数表达式(Initializer Expression) Initializer表达式用来给某个Type初始化。 它的形式如下: -`expression`.init(`initializer arguments`) +> `expression`.init(`initializer arguments`) (Initializer表达式用来给某个Type初始化。) 跟函数(function)不同, initializer 不能返回值。 ```swift var x = SomeClass.someClassFunction // ok var y = SomeClass.init // error -```swift +``` 可以通过 initializer 表达式来委托调用(delegate to )到superclass的initializers. @@ -523,15 +506,14 @@ class SomeSubClass: SomeSuperClass { } ``` -> initializer表达式的语法 -> -> *initializer-expression* → *postfix-expression*­.­init­ +> 构造器表达式语法 +> *构造器表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** **init** ### 显式成员表达式(Explicit Member Expression) 显示成员表达式允许我们访问type, tuple, module的成员变量。它的形式如下: -`expression`.`member name` +> `expression`.`member name` 该member 就是某个type在声明时候所定义(declaration or extension) 的变量, 例如: @@ -554,25 +536,23 @@ t.0 = t.1 The members of a module access the top-level declarations of that module. (不确定:对于某个module的member的调用,只能调用在top-level声明中的member.) -> 显示成员表达式的语法 -> -> *explicit-member-expression* → *postfix-expression*­.­*decimal-digit*­ -> *explicit-member-expression* → *postfix-expression*­.­*identifier*­*generic-argument-clause*(opt) +> 显式成员表达式语法 +> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit) +> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ ### 后缀self表达式(Postfix Self Expression) 后缀表达式由 某个表达式 + '.self' 组成. 形式如下: -`expression`.self -`type`.self +> `expression`.self +> `type`.self 形式1 表示会返回 expression 的值。例如: x.self 返回 x 形式2:返回对应的type。我们可以用它来动态的获取某个instance的type。 -> 后缀self表达式的语法 -> -> *postfix-self-expression* → *postfix-expression*­.­self­ +> 后置Self 表达式语法 +> *后置self表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** **self** ### dynamic表达式(Dynamic Type Expression) @@ -580,7 +560,7 @@ The members of a module access the top-level declarations of that module. dynamicType 表达式由 某个表达式 + '.dynamicType' 组成。 -`expression`.dynamicType +> `expression`.dynamicType 上面的形式中, expression 不能是某type的名字(当然了,如果我都知道它的名字了还需要动态来获取它吗)。动态类型表达式会返回"运行时"某个instance的type, 具体请看下面的列子: @@ -603,41 +583,38 @@ someInstance.dynamicType.printClassName() // prints "SomeSubClass" ``` -> dynamic type 表达式 -> -> *dynamic-type-expression* → *postfix-expression*­.­dynamicType­ +> 动态类型表达式语法 +> *动态类型表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** **dynamicType** ### 附属脚本表达式(Subscript Expression) 附属脚本表达式提供了通过附属脚本访问getter/setter 的方法。它的形式是: -`expression`[`index expressions`] +> `expression`[`index expressions`] 可以通过附属脚本表达式通过getter获取某个值,或者通过setter赋予某个值. 关于subscript的声明,请参见: Protocol Subscript Declaration. -> 附属脚本表达式的语法 -> -> *subscript-expression* → *postfix-expression*­[­*expression-list*­]­ +> 附属脚本表达式语法 +> *附属脚本表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **[** [*表达式列表*](..\chapter3\04_Expressions.html#expression_list) **]** ### 强制取值表达式(Forced-Value Expression) 强制取值表达式用来获取某个目标表达式的值(该目标表达式的值必须不是nil )。它的形式如下: -`expression`! +> `expression`! 如果该表达式的值不是nil, 则返回对应的值。 否则,抛出运行时错误(runtime error)。 -> 强制取值表达式的语法 -> -> *forced-value-expression* → *postfix-expression*­!­ +> 强制取值(Forced Value)语法 +> *强制取值(Forced Value)表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **!** ### 可选链表达式(Optional-Chaining Expression) 可选链表达式由目标表达式 + '?' 组成,形式如下: -`expression`? +> `expression`? 后缀'?' 返回目标表达式的值,把它做为可选的参数传递给后续的表达式 @@ -658,6 +635,5 @@ if let unwrappedC = c { } ``` -> 可选链表达式的语法 -> -> *optional-chaining-expression* → *postfix-expression*­?­ +> 可选链表达式语法 +> *可选链表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **?** diff --git a/source/chapter3/09_Summary_of_the_Grammar.md b/source/chapter3/09_Summary_of_the_Grammar.md index f301ddc4..d2e4619d 100644 --- a/source/chapter3/09_Summary_of_the_Grammar.md +++ b/source/chapter3/09_Summary_of_the_Grammar.md @@ -90,7 +90,7 @@ _________________ > 标记语句语法 > *标记语句(Labeled Statement)* → [*语句标签*](..\chapter3\10_Statements.html#statement_label) [*循环语句*](..\chapter3\10_Statements.html#loop_statement) | [*语句标签*](..\chapter3\10_Statements.html#statement_label) [*switch语句*](..\chapter3\10_Statements.html#switch_statement) > *语句标签* → [*标签名称*](..\chapter3\10_Statements.html#label_name) **:** -> *标签名称* → [*标识符*](LexicalStructure.html#identifier) +> *标签名称* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)

@@ -181,7 +181,7 @@ _________________ > *导入声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **import** [*导入类型*](..\chapter3\05_Declarations.html#import_kind) _可选_ [*导入路径*](..\chapter3\05_Declarations.html#import_path) > *导入类型* → **typealias** | **struct** | **class** | **enum** | **protocol** | **var** | **func** > *导入路径* → [*导入路径标识符*](..\chapter3\05_Declarations.html#import_path_identifier) | [*导入路径标识符*](..\chapter3\05_Declarations.html#import_path_identifier) **.** [*导入路径*](..\chapter3\05_Declarations.html#import_path) -> *导入路径标识符* → [*标识符*](LexicalStructure.html#identifier) | [*运算符*](LexicalStructure.html#operator) +> *导入路径标识符* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) | [*运算符*](..\chapter3\02_Lexical_Structure.html#operator)

@@ -200,12 +200,12 @@ _________________ > *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*变量名*](..\chapter3\05_Declarations.html#variable_name) [*类型注解*](..\chapter3\03_Types.html#type_annotation) [*getter-setter关键字(Keyword)块*](..\chapter3\05_Declarations.html#getter_setter_keyword_block) > *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*变量名*](..\chapter3\05_Declarations.html#variable_name) [*类型注解*](..\chapter3\03_Types.html#type_annotation) [*构造器*](..\chapter3\05_Declarations.html#initializer) _可选_ [*willSet-didSet代码块*](..\chapter3\05_Declarations.html#willSet_didSet_block) > *变量声明头(Head)* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明描述符(Specifiers)列表*](..\chapter3\05_Declarations.html#declaration_specifiers) _可选_ **var** -> *变量名称* → [*标识符*](LexicalStructure.html#identifier) +> *变量名称* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) > *getter-setter块* → **{** [*getter子句*](..\chapter3\05_Declarations.html#getter_clause) [*setter子句*](..\chapter3\05_Declarations.html#setter_clause) _可选_ **}** > *getter-setter块* → **{** [*setter子句*](..\chapter3\05_Declarations.html#setter_clause) [*getter子句*](..\chapter3\05_Declarations.html#getter_clause) **}** > *getter子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **get** [*代码块*](..\chapter3\05_Declarations.html#code_block) > *setter子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **set** [*setter名称*](..\chapter3\05_Declarations.html#setter_name) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block) -> *setter名称* → **(** [*标识符*](LexicalStructure.html#identifier) **)** +> *setter名称* → **(** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) **)** > *getter-setter关键字(Keyword)块* → **{** [*getter关键字(Keyword)子句*](..\chapter3\05_Declarations.html#getter_keyword_clause) [*setter关键字(Keyword)子句*](..\chapter3\05_Declarations.html#setter_keyword_clause) _可选_ **}** > *getter-setter关键字(Keyword)块* → **{** [*setter关键字(Keyword)子句*](..\chapter3\05_Declarations.html#setter_keyword_clause) [*getter关键字(Keyword)子句*](..\chapter3\05_Declarations.html#getter_keyword_clause) **}** > *getter关键字(Keyword)子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **get** @@ -220,7 +220,7 @@ _________________ > 类型别名声明语法 > *类型别名声明* → [*类型别名头(Head)*](..\chapter3\05_Declarations.html#typealias_head) [*类型别名赋值*](..\chapter3\05_Declarations.html#typealias_assignment) > *类型别名头(Head)* → **typealias** [*类型别名名称*](..\chapter3\05_Declarations.html#typealias_name) -> *类型别名名称* → [*标识符*](LexicalStructure.html#identifier) +> *类型别名名称* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) > *类型别名赋值* → **=** [*类型*](..\chapter3\03_Types.html#type)

@@ -228,7 +228,7 @@ _________________ > 函数声明语法 > *函数声明* → [*函数头*](..\chapter3\05_Declarations.html#function_head) [*函数名*](..\chapter3\05_Declarations.html#function_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*函数签名(Signature)*](..\chapter3\05_Declarations.html#function_signature) [*函数体*](..\chapter3\05_Declarations.html#function_body) > *函数头* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明描述符(Specifiers)列表*](..\chapter3\05_Declarations.html#declaration_specifiers) _可选_ **func** -> *函数名* → [*标识符*](LexicalStructure.html#identifier) | [*运算符*](LexicalStructure.html#operator) +> *函数名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) | [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) > *函数签名(Signature)* → [*parameter-clauses*](..\chapter3\05_Declarations.html#parameter_clauses) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ > *函数结果* → **->** [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type) > *函数体* → [*代码块*](..\chapter3\05_Declarations.html#code_block) @@ -238,8 +238,8 @@ _________________ > *参数* → **inout** _可选_ **let** _可选_ **#** _可选_ [*参数名*](..\chapter3\05_Declarations.html#parameter_name) [*本地参数名*](..\chapter3\05_Declarations.html#local_parameter_name) _可选_ [*类型注解*](..\chapter3\03_Types.html#type_annotation) [*默认参数子句*](..\chapter3\05_Declarations.html#default_argument_clause) _可选_ > *参数* → **inout** _可选_ **var** **#** _可选_ [*参数名*](..\chapter3\05_Declarations.html#parameter_name) [*本地参数名*](..\chapter3\05_Declarations.html#local_parameter_name) _可选_ [*类型注解*](..\chapter3\03_Types.html#type_annotation) [*默认参数子句*](..\chapter3\05_Declarations.html#default_argument_clause) _可选_ > *参数* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type) -> *参数名* → [*标识符*](LexicalStructure.html#identifier) | **_** -> *本地参数名* → [*标识符*](LexicalStructure.html#identifier) | **_** +> *参数名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) | **_** +> *本地参数名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) | **_** > *默认参数子句* → **=** [*表达式*](..\chapter3\04_Expressions.html#expression)

@@ -252,35 +252,35 @@ _________________ > *联合式(Union Style)的枚举case子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **case** [*联合式(Union Style)的枚举case列表*](..\chapter3\05_Declarations.html#union_style_enum_case_list) > *联合式(Union Style)的枚举case列表* → [*联合式(Union Style)的case*](..\chapter3\05_Declarations.html#union_style_enum_case) | [*联合式(Union Style)的case*](..\chapter3\05_Declarations.html#union_style_enum_case) **,** [*联合式(Union Style)的枚举case列表*](..\chapter3\05_Declarations.html#union_style_enum_case_list) > *联合式(Union Style)的case* → [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*元组类型*](..\chapter3\03_Types.html#tuple_type) _可选_ -> *枚举名* → [*标识符*](LexicalStructure.html#identifier) -> *枚举的case名* → [*标识符*](LexicalStructure.html#identifier) +> *枚举名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) +> *枚举的case名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) > *原始值式枚举* → [*枚举名*](..\chapter3\05_Declarations.html#enum_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ **:** [*类型标识*](..\chapter3\03_Types.html#type_identifier) **{** [*原始值式枚举成员列表*](..\chapter3\05_Declarations.html#raw_value_style_enum_members) _可选_ **}** > *原始值式枚举成员列表* → [*原始值式枚举成员*](..\chapter3\05_Declarations.html#raw_value_style_enum_member) [*原始值式枚举成员列表*](..\chapter3\05_Declarations.html#raw_value_style_enum_members) _可选_ > *原始值式枚举成员* → [*声明*](..\chapter3\05_Declarations.html#declaration) | [*原始值式枚举case子句*](..\chapter3\05_Declarations.html#raw_value_style_enum_case_clause) > *原始值式枚举case子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **case** [*原始值式枚举case列表*](..\chapter3\05_Declarations.html#raw_value_style_enum_case_list) > *原始值式枚举case列表* → [*原始值式枚举case*](..\chapter3\05_Declarations.html#raw_value_style_enum_case) | [*原始值式枚举case*](..\chapter3\05_Declarations.html#raw_value_style_enum_case) **,** [*原始值式枚举case列表*](..\chapter3\05_Declarations.html#raw_value_style_enum_case_list) > *原始值式枚举case* → [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*原始值赋值*](..\chapter3\05_Declarations.html#raw_value_assignment) _可选_ -> *原始值赋值* → **=** [*字面量*](LexicalStructure.html#literal) +> *原始值赋值* → **=** [*字面量*](..\chapter3\02_Lexical_Structure.html#literal)

> 结构体声明语法 > *结构体声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **struct** [*结构体名称*](..\chapter3\05_Declarations.html#struct_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*结构体主体*](..\chapter3\05_Declarations.html#struct_body) -> *结构体名称* → [*标识符*](LexicalStructure.html#identifier) +> *结构体名称* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) > *结构体主体* → **{** [*声明(Declarations)列表*](..\chapter3\05_Declarations.html#declarations) _可选_ **}**

> 类声明语法 > *类声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **class** [*类名*](..\chapter3\05_Declarations.html#class_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*类主体*](..\chapter3\05_Declarations.html#class_body) -> *类名* → [*标识符*](LexicalStructure.html#identifier) +> *类名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) > *类主体* → **{** [*声明(Declarations)列表*](..\chapter3\05_Declarations.html#declarations) _可选_ **}**

> 协议(Protocol)声明语法 > *协议声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **protocol** [*协议名*](..\chapter3\05_Declarations.html#protocol_name) [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*协议主体*](..\chapter3\05_Declarations.html#protocol_body) -> *协议名* → [*标识符*](LexicalStructure.html#identifier) +> *协议名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) > *协议主体* → **{** [*协议成员声明(Declarations)列表*](..\chapter3\05_Declarations.html#protocol_member_declarations) _可选_ **}** > *协议成员声明* → [*协议属性声明*](..\chapter3\05_Declarations.html#protocol_property_declaration) > *协议成员声明* → [*协议方法声明*](..\chapter3\05_Declarations.html#protocol_method_declaration) @@ -345,9 +345,9 @@ _________________ > 运算符声明语法 > *运算符声明* → [*前置运算符声明*](..\chapter3\05_Declarations.html#prefix_operator_declaration) | [*后置运算符声明*](..\chapter3\05_Declarations.html#postfix_operator_declaration) | [*中置运算符声明*](..\chapter3\05_Declarations.html#infix_operator_declaration) -> *前置运算符声明* → **运算符** **prefix** [*运算符*](LexicalStructure.html#operator) **{** **}** -> *后置运算符声明* → **运算符** **postfix** [*运算符*](LexicalStructure.html#operator) **{** **}** -> *中置运算符声明* → **运算符** **infix** [*运算符*](LexicalStructure.html#operator) **{** [*中置运算符属性*](..\chapter3\05_Declarations.html#infix_operator_attributes) _可选_ **}** +> *前置运算符声明* → **运算符** **prefix** [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) **{** **}** +> *后置运算符声明* → **运算符** **postfix** [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) **{** **}** +> *中置运算符声明* → **运算符** **infix** [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) **{** [*中置运算符属性*](..\chapter3\05_Declarations.html#infix_operator_attributes) _可选_ **}** > *中置运算符属性* → [*优先级子句*](..\chapter3\05_Declarations.html#precedence_clause) _可选_ [*结和性子句*](..\chapter3\05_Declarations.html#associativity_clause) _可选_ > *优先级子句* → **precedence** [*优先级水平*](..\chapter3\05_Declarations.html#precedence_level) > *优先级水平* → 数值 0 到 255 @@ -374,7 +374,7 @@ _________________

> 标识符模式语法 -> *标识符模式* → [*标识符*](LexicalStructure.html#identifier) +> *标识符模式* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)

@@ -410,7 +410,7 @@ _________________ > 特性语法 > *特色* → **@** [*特性名*](..\chapter3\06_Attributes.html#attribute_name) [*特性参数子句*](..\chapter3\06_Attributes.html#attribute_argument_clause) _可选_ -> *特性名* → [*标识符*](LexicalStructure.html#identifier) +> *特性名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) > *特性参数子句* → **(** [*平衡令牌列表*](..\chapter3\06_Attributes.html#balanced_tokens) _可选_ **)** > *特性(Attributes)列表* → [*特色*](..\chapter3\06_Attributes.html#attribute) [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ > *平衡令牌列表* → [*平衡令牌*](..\chapter3\06_Attributes.html#balanced_token) [*平衡令牌列表*](..\chapter3\06_Attributes.html#balanced_tokens) _可选_ @@ -430,14 +430,14 @@ _________________

> 前置表达式语法 -> *前置表达式* → [*前置运算符*](LexicalStructure.html#prefix_operator) _可选_ [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) +> *前置表达式* → [*前置运算符*](..\chapter3\02_Lexical_Structure.html#prefix_operator) _可选_ [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) > *前置表达式* → [*写入写出(in-out)表达式*](..\chapter3\04_Expressions.html#in_out_expression) -> *写入写出(in-out)表达式* → **&** [*标识符*](LexicalStructure.html#identifier) +> *写入写出(in-out)表达式* → **&** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)

> 二元表达式语法 -> *二元表达式* → [*二元运算符*](LexicalStructure.html#binary_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) +> *二元表达式* → [*二元运算符*](..\chapter3\02_Lexical_Structure.html#binary_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) > *二元表达式* → [*赋值运算符*](..\chapter3\04_Expressions.html#assignment_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) > *二元表达式* → [*条件运算符*](..\chapter3\04_Expressions.html#conditional_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) > *二元表达式* → [*类型转换运算符*](..\chapter3\04_Expressions.html#type_casting_operator) @@ -450,8 +450,8 @@ _________________

-> 条件运算符语法 -> *条件运算符* → **?** [*表达式*](..\chapter3\04_Expressions.html#expression) **:** +> 三元条件运算符语法 +> *三元条件运算符* → **?** [*表达式*](..\chapter3\04_Expressions.html#expression) **:**

@@ -461,7 +461,7 @@ _________________

> 主表达式语法 -> *主表达式* → [*标识符*](LexicalStructure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ +> *主表达式* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ > *主表达式* → [*字面量表达式*](..\chapter3\04_Expressions.html#literal_expression) > *主表达式* → [*self表达式*](..\chapter3\04_Expressions.html#self_expression) > *主表达式* → [*超类表达式*](..\chapter3\04_Expressions.html#superclass_expression) @@ -473,7 +473,7 @@ _________________

> 字面量表达式语法 -> *字面量表达式* → [*字面量*](LexicalStructure.html#literal) +> *字面量表达式* → [*字面量*](..\chapter3\02_Lexical_Structure.html#literal) > *字面量表达式* → [*数组字面量*](..\chapter3\04_Expressions.html#array_literal) | [*字典字面量*](..\chapter3\04_Expressions.html#dictionary_literal) > *字面量表达式* → **__FILE__** | **__LINE__** | **__COLUMN__** | **__FUNCTION__** > *数组字面量* → **[** [*数组字面量项列表*](..\chapter3\04_Expressions.html#array_literal_items) _可选_ **]** @@ -487,7 +487,7 @@ _________________ > Self 表达式语法 > *self表达式* → **self** -> *self表达式* → **self** **.** [*标识符*](LexicalStructure.html#identifier) +> *self表达式* → **self** **.** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) > *self表达式* → **self** **[** [*表达式*](..\chapter3\04_Expressions.html#expression) **]** > *self表达式* → **self** **.** **init** @@ -495,7 +495,7 @@ _________________ > 超类表达式语法 > *超类表达式* → [*超类方法表达式*](..\chapter3\04_Expressions.html#superclass_method_expression) | [*超类下标表达式*](..\chapter3\04_Expressions.html#超类下标表达式) | [*超类构造器表达式*](..\chapter3\04_Expressions.html#superclass_initializer_expression) -> *超类方法表达式* → **super** **.** [*标识符*](LexicalStructure.html#identifier) +> *超类方法表达式* → **super** **.** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) > *超类下标表达式* → **super** **[** [*表达式*](..\chapter3\04_Expressions.html#expression) **]** > *超类构造器表达式* → **super** **.** **init** @@ -504,9 +504,9 @@ _________________ > 闭包表达式语法 > *闭包表达式* → **{** [*闭包签名(Signational)*](..\chapter3\04_Expressions.html#closure_signature) _可选_ [*多条语句(Statements)*](..\chapter3\10_Statements.html#statements) **}** > *闭包签名(Signational)* → [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** -> *闭包签名(Signational)* → [*标识符列表*](LexicalStructure.html#identifier_list) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** +> *闭包签名(Signational)* → [*标识符列表*](..\chapter3\02_Lexical_Structure.html#identifier_list) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** > *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** -> *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) [*标识符列表*](LexicalStructure.html#identifier_list) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** +> *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) [*标识符列表*](..\chapter3\02_Lexical_Structure.html#identifier_list) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** > *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) **in** > *捕获(Capature)列表* → **[** [*捕获(Capature)说明符*](..\chapter3\04_Expressions.html#capture_specifier) [*表达式*](..\chapter3\04_Expressions.html#expression) **]** > *捕获(Capature)说明符* → **weak** | **unowned** | **unowned(safe)** | **unowned(unsafe)** @@ -514,14 +514,14 @@ _________________

> 隐式成员表达式语法 -> *隐式成员表达式* → **.** [*标识符*](LexicalStructure.html#identifier) +> *隐式成员表达式* → **.** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)

> 圆括号表达式(Parenthesized Expression)语法 > *圆括号表达式* → **(** [*表达式元素列表*](..\chapter3\04_Expressions.html#expression_element_list) _可选_ **)** > *表达式元素列表* → [*表达式元素*](..\chapter3\04_Expressions.html#expression_element) | [*表达式元素*](..\chapter3\04_Expressions.html#expression_element) **,** [*表达式元素列表*](..\chapter3\04_Expressions.html#expression_element_list) -> *表达式元素* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*标识符*](LexicalStructure.html#identifier) **:** [*表达式*](..\chapter3\04_Expressions.html#expression) +> *表达式元素* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) **:** [*表达式*](..\chapter3\04_Expressions.html#expression)

@@ -532,7 +532,7 @@ _________________ > 后置表达式语法 > *后置表达式* → [*主表达式*](..\chapter3\04_Expressions.html#primary_expression) -> *后置表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) [*后置运算符*](LexicalStructure.html#postfix_operator) +> *后置表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) [*后置运算符*](..\chapter3\02_Lexical_Structure.html#postfix_operator) > *后置表达式* → [*函数调用表达式*](..\chapter3\04_Expressions.html#function_call_expression) > *后置表达式* → [*构造器表达式*](..\chapter3\04_Expressions.html#initializer_expression) > *后置表达式* → [*显示成员表达式*](..\chapter3\04_Expressions.html#explicit_member_expression) @@ -557,12 +557,12 @@ _________________

> 显式成员表达式语法 -> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*十进制数字*](LexicalStructure.html#decimal_digit) -> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*标识符*](LexicalStructure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ +> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit) +> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_

-> Self 表达式语法 +> 后置Self 表达式语法 > *后置self表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** **self**

@@ -572,8 +572,8 @@ _________________

-> 下标表达式语法 -> *下标表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **[** [*表达式列表*](..\chapter3\04_Expressions.html#expression_list) **]** +> 附属脚本表达式语法 +> *附属脚本表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **[** [*表达式列表*](..\chapter3\04_Expressions.html#expression_list) **]**

@@ -589,10 +589,10 @@ _________________ ## 词法结构 > 标识符语法 -> *标识符* → [*标识符头(Head)*](LexicalStructure.html#identifier_head) [*标识符字符列表*](LexicalStructure.html#identifier_characters) _可选_ -> *标识符* → **`** [*标识符头(Head)*](LexicalStructure.html#identifier_head) [*标识符字符列表*](LexicalStructure.html#identifier_characters) _可选_ **`** -> *标识符* → [*隐式参数名*](LexicalStructure.html#implicit_parameter_name) -> *标识符列表* → [*标识符*](LexicalStructure.html#identifier) | [*标识符*](LexicalStructure.html#identifier) **,** [*标识符列表*](LexicalStructure.html#identifier_list) +> *标识符* → [*标识符头(Head)*](..\chapter3\02_Lexical_Structure.html#identifier_head) [*标识符字符列表*](..\chapter3\02_Lexical_Structure.html#identifier_characters) _可选_ +> *标识符* → **`** [*标识符头(Head)*](..\chapter3\02_Lexical_Structure.html#identifier_head) [*标识符字符列表*](..\chapter3\02_Lexical_Structure.html#identifier_characters) _可选_ **`** +> *标识符* → [*隐式参数名*](..\chapter3\02_Lexical_Structure.html#implicit_parameter_name) +> *标识符列表* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) | [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) **,** [*标识符列表*](..\chapter3\02_Lexical_Structure.html#identifier_list) > *标识符头(Head)* → Upper- or lowercase letter A through Z > *标识符头(Head)* → U+00A8, U+00AA, U+00AD, U+00AF, U+00B2–U+00B5, or U+00B7–U+00BA > *标识符头(Head)* → U+00BC–U+00BE, U+00C0–U+00D6, U+00D8–U+00F6, or U+00F8–U+00FF @@ -610,49 +610,49 @@ _________________ > *标识符头(Head)* → U+D0000–U+DFFFD or U+E0000–U+EFFFD > *标识符字符* → 数值 0 到 9 > *标识符字符* → U+0300–U+036F, U+1DC0–U+1DFF, U+20D0–U+20FF, or U+FE20–U+FE2F -> *标识符字符* → [*标识符头(Head)*](LexicalStructure.html#identifier_head) -> *标识符字符列表* → [*标识符字符*](LexicalStructure.html#identifier_character) [*标识符字符列表*](LexicalStructure.html#identifier_characters) _可选_ -> *隐式参数名* → **$** [*十进制数字列表*](LexicalStructure.html#decimal_digits) +> *标识符字符* → [*标识符头(Head)*](..\chapter3\02_Lexical_Structure.html#identifier_head) +> *标识符字符列表* → [*标识符字符*](..\chapter3\02_Lexical_Structure.html#identifier_character) [*标识符字符列表*](..\chapter3\02_Lexical_Structure.html#identifier_characters) _可选_ +> *隐式参数名* → **$** [*十进制数字列表*](..\chapter3\02_Lexical_Structure.html#decimal_digits)

> 字面量语法 -> *字面量* → [*整型字面量*](LexicalStructure.html#integer_literal) | [*浮点数字面量*](LexicalStructure.html#floating_point_literal) | [*字符串字面量*](LexicalStructure.html#string_literal) +> *字面量* → [*整型字面量*](..\chapter3\02_Lexical_Structure.html#integer_literal) | [*浮点数字面量*](..\chapter3\02_Lexical_Structure.html#floating_point_literal) | [*字符串字面量*](..\chapter3\02_Lexical_Structure.html#string_literal)

> 整型字面量语法 -> *整型字面量* → [*二进制字面量*](LexicalStructure.html#binary_literal) -> *整型字面量* → [*八进制字面量*](LexicalStructure.html#octal_literal) -> *整型字面量* → [*十进制字面量*](LexicalStructure.html#decimal_literal) -> *整型字面量* → [*十六进制字面量*](LexicalStructure.html#hexadecimal_literal) -> *二进制字面量* → **0b** [*二进制数字*](LexicalStructure.html#binary_digit) [*二进制字面量字符列表*](LexicalStructure.html#binary_literal_characters) _可选_ +> *整型字面量* → [*二进制字面量*](..\chapter3\02_Lexical_Structure.html#binary_literal) +> *整型字面量* → [*八进制字面量*](..\chapter3\02_Lexical_Structure.html#octal_literal) +> *整型字面量* → [*十进制字面量*](..\chapter3\02_Lexical_Structure.html#decimal_literal) +> *整型字面量* → [*十六进制字面量*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal) +> *二进制字面量* → **0b** [*二进制数字*](..\chapter3\02_Lexical_Structure.html#binary_digit) [*二进制字面量字符列表*](..\chapter3\02_Lexical_Structure.html#binary_literal_characters) _可选_ > *二进制数字* → 数值 0 到 1 -> *二进制字面量字符* → [*二进制数字*](LexicalStructure.html#binary_digit) | **_** -> *二进制字面量字符列表* → [*二进制字面量字符*](LexicalStructure.html#binary_literal_character) [*二进制字面量字符列表*](LexicalStructure.html#binary_literal_characters) _可选_ -> *八进制字面量* → **0o** [*八进字数字*](LexicalStructure.html#octal_digit) [*八进制字符列表*](LexicalStructure.html#octal_literal_characters) _可选_ +> *二进制字面量字符* → [*二进制数字*](..\chapter3\02_Lexical_Structure.html#binary_digit) | **_** +> *二进制字面量字符列表* → [*二进制字面量字符*](..\chapter3\02_Lexical_Structure.html#binary_literal_character) [*二进制字面量字符列表*](..\chapter3\02_Lexical_Structure.html#binary_literal_characters) _可选_ +> *八进制字面量* → **0o** [*八进字数字*](..\chapter3\02_Lexical_Structure.html#octal_digit) [*八进制字符列表*](..\chapter3\02_Lexical_Structure.html#octal_literal_characters) _可选_ > *八进字数字* → 数值 0 到 7 -> *八进制字符* → [*八进字数字*](LexicalStructure.html#octal_digit) | **_** -> *八进制字符列表* → [*八进制字符*](LexicalStructure.html#octal_literal_character) [*八进制字符列表*](LexicalStructure.html#octal_literal_characters) _可选_ -> *十进制字面量* → [*十进制数字*](LexicalStructure.html#decimal_digit) [*十进制字符列表*](LexicalStructure.html#decimal_literal_characters) _可选_ +> *八进制字符* → [*八进字数字*](..\chapter3\02_Lexical_Structure.html#octal_digit) | **_** +> *八进制字符列表* → [*八进制字符*](..\chapter3\02_Lexical_Structure.html#octal_literal_character) [*八进制字符列表*](..\chapter3\02_Lexical_Structure.html#octal_literal_characters) _可选_ +> *十进制字面量* → [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit) [*十进制字符列表*](..\chapter3\02_Lexical_Structure.html#decimal_literal_characters) _可选_ > *十进制数字* → 数值 0 到 9 -> *十进制数字列表* → [*十进制数字*](LexicalStructure.html#decimal_digit) [*十进制数字列表*](LexicalStructure.html#decimal_digits) _可选_ -> *十进制字符* → [*十进制数字*](LexicalStructure.html#decimal_digit) | **_** -> *十进制字符列表* → [*十进制字符*](LexicalStructure.html#decimal_literal_character) [*十进制字符列表*](LexicalStructure.html#decimal_literal_characters) _可选_ -> *十六进制字面量* → **0x** [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制字面量字符列表*](LexicalStructure.html#hexadecimal_literal_characters) _可选_ +> *十进制数字列表* → [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit) [*十进制数字列表*](..\chapter3\02_Lexical_Structure.html#decimal_digits) _可选_ +> *十进制字符* → [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit) | **_** +> *十进制字符列表* → [*十进制字符*](..\chapter3\02_Lexical_Structure.html#decimal_literal_character) [*十进制字符列表*](..\chapter3\02_Lexical_Structure.html#decimal_literal_characters) _可选_ +> *十六进制字面量* → **0x** [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制字面量字符列表*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal_characters) _可选_ > *十六进制数字* → 数值 0 到 9, a through f, or A through F -> *十六进制字符* → [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) | **_** -> *十六进制字面量字符列表* → [*十六进制字符*](LexicalStructure.html#hexadecimal_literal_character) [*十六进制字面量字符列表*](LexicalStructure.html#hexadecimal_literal_characters) _可选_ +> *十六进制字符* → [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) | **_** +> *十六进制字面量字符列表* → [*十六进制字符*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal_character) [*十六进制字面量字符列表*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal_characters) _可选_

> 浮点型字面量语法 -> *浮点数字面量* → [*十进制字面量*](LexicalStructure.html#decimal_literal) [*十进制分数*](LexicalStructure.html#decimal_fraction) _可选_ [*十进制指数*](LexicalStructure.html#decimal_exponent) _可选_ -> *浮点数字面量* → [*十六进制字面量*](LexicalStructure.html#hexadecimal_literal) [*十六进制分数*](LexicalStructure.html#hexadecimal_fraction) _可选_ [*十六进制指数*](LexicalStructure.html#hexadecimal_exponent) -> *十进制分数* → **.** [*十进制字面量*](LexicalStructure.html#decimal_literal) -> *十进制指数* → [*浮点数e*](LexicalStructure.html#floating_point_e) [*正负号*](LexicalStructure.html#sign) _可选_ [*十进制字面量*](LexicalStructure.html#decimal_literal) -> *十六进制分数* → **.** [*十六进制字面量*](LexicalStructure.html#hexadecimal_literal) _可选_ -> *十六进制指数* → [*浮点数p*](LexicalStructure.html#floating_point_p) [*正负号*](LexicalStructure.html#sign) _可选_ [*十六进制字面量*](LexicalStructure.html#hexadecimal_literal) +> *浮点数字面量* → [*十进制字面量*](..\chapter3\02_Lexical_Structure.html#decimal_literal) [*十进制分数*](..\chapter3\02_Lexical_Structure.html#decimal_fraction) _可选_ [*十进制指数*](..\chapter3\02_Lexical_Structure.html#decimal_exponent) _可选_ +> *浮点数字面量* → [*十六进制字面量*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal) [*十六进制分数*](..\chapter3\02_Lexical_Structure.html#hexadecimal_fraction) _可选_ [*十六进制指数*](..\chapter3\02_Lexical_Structure.html#hexadecimal_exponent) +> *十进制分数* → **.** [*十进制字面量*](..\chapter3\02_Lexical_Structure.html#decimal_literal) +> *十进制指数* → [*浮点数e*](..\chapter3\02_Lexical_Structure.html#floating_point_e) [*正负号*](..\chapter3\02_Lexical_Structure.html#sign) _可选_ [*十进制字面量*](..\chapter3\02_Lexical_Structure.html#decimal_literal) +> *十六进制分数* → **.** [*十六进制字面量*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal) _可选_ +> *十六进制指数* → [*浮点数p*](..\chapter3\02_Lexical_Structure.html#floating_point_p) [*正负号*](..\chapter3\02_Lexical_Structure.html#sign) _可选_ [*十六进制字面量*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal) > *浮点数e* → **e** | **E** > *浮点数p* → **p** | **P** > *正负号* → **+** | **-** @@ -660,24 +660,24 @@ _________________

> 字符型字面量语法 -> *字符串字面量* → **"** [*引用文本*](LexicalStructure.html#quoted_text) **"** -> *引用文本* → [*引用文本条目*](LexicalStructure.html#quoted_text_item) [*引用文本*](LexicalStructure.html#quoted_text) _可选_ -> *引用文本条目* → [*转义字符*](LexicalStructure.html#escaped_character) +> *字符串字面量* → **"** [*引用文本*](..\chapter3\02_Lexical_Structure.html#quoted_text) **"** +> *引用文本* → [*引用文本条目*](..\chapter3\02_Lexical_Structure.html#quoted_text_item) [*引用文本*](..\chapter3\02_Lexical_Structure.html#quoted_text) _可选_ +> *引用文本条目* → [*转义字符*](..\chapter3\02_Lexical_Structure.html#escaped_character) > *引用文本条目* → **\(** [*表达式*](..\chapter3\04_Expressions.html#expression) **)** > *引用文本条目* → 除了"­, \­, U+000A, or U+000D的所有Unicode的字符 > *转义字符* → **\0** | **\\** | **\t** | **\n** | **\r** | **\"** | **\'** -> *转义字符* → **\x** [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) -> *转义字符* → **\u** [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) -> *转义字符* → **\U** [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) +> *转义字符* → **\x** [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) +> *转义字符* → **\u** [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) +> *转义字符* → **\U** [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit)

> 运算符语法语法 -> *运算符* → [*运算符字符*](LexicalStructure.html#operator_character) [*运算符*](LexicalStructure.html#operator) _可选_ +> *运算符* → [*运算符字符*](..\chapter3\02_Lexical_Structure.html#operator_character) [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) _可选_ > *运算符字符* → **/** | **=** | **-** | **+** | **!** | ***** | **%** | **<** | **>** | **&** | **|** | **^** | **~** | **.** -> *二元运算符* → [*运算符*](LexicalStructure.html#operator) -> *前置运算符* → [*运算符*](LexicalStructure.html#operator) -> *后置运算符* → [*运算符*](LexicalStructure.html#operator) +> *二元运算符* → [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) +> *前置运算符* → [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) +> *后置运算符* → [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) ## 类型 @@ -694,7 +694,7 @@ _________________ > 类型标识语法 > *类型标识* → [*类型名称*](..\chapter3\03_Types.html#type_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ | [*类型名称*](..\chapter3\03_Types.html#type_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ **.** [*类型标识*](..\chapter3\03_Types.html#type_identifier) -> *类名* → [*标识符*](LexicalStructure.html#identifier) +> *类名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)

@@ -703,7 +703,7 @@ _________________ > *元组类型主体* → [*元组类型的元素列表*](..\chapter3\03_Types.html#tuple_type_element_list) **...** _可选_ > *元组类型的元素列表* → [*元组类型的元素*](..\chapter3\03_Types.html#tuple_type_element) | [*元组类型的元素*](..\chapter3\03_Types.html#tuple_type_element) **,** [*元组类型的元素列表*](..\chapter3\03_Types.html#tuple_type_element_list) > *元组类型的元素* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **inout** _可选_ [*类型*](..\chapter3\03_Types.html#type) | **inout** _可选_ [*元素名*](..\chapter3\03_Types.html#element_name) [*类型注解*](..\chapter3\03_Types.html#type_annotation) -> *元素名* → [*标识符*](LexicalStructure.html#identifier) +> *元素名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)

From 698efafc26795151faeb79f5a98eab5a58d5721e Mon Sep 17 00:00:00 2001 From: stanzhai Date: Sat, 14 Jun 2014 21:42:52 +0800 Subject: [PATCH 14/14] fix 3.5 declarations --- source/chapter2/18_Type_Casting.md | 20 +-- source/chapter3/05_Declarations.md | 266 +++++++++++++++-------------- 2 files changed, 148 insertions(+), 138 deletions(-) diff --git a/source/chapter2/18_Type_Casting.md b/source/chapter2/18_Type_Casting.md index 4f4f2477..9dd556f5 100644 --- a/source/chapter2/18_Type_Casting.md +++ b/source/chapter2/18_Type_Casting.md @@ -1,7 +1,7 @@ > 翻译:xiehurricane > 校对:happyming -# 类型转换(Type Casting) +# 类型检查(Type Casting) ----------------- 本页包含内容: @@ -9,7 +9,7 @@ - [定义一个类层次作为例子](#defining_a_class_hierarchy_for_type_casting) - [检查类型](#checking_type) - [向下转型(Downcasting)](#downcasting) -- [`Any`和`AnyObject`的类型转换](#type_casting_for_any_and_anyobject) +- [`Any`和`AnyObject`的类型检查](#type_casting_for_any_and_anyobject) _类型检查_是一种检查类实例的方式,并且或者也是让实例作为它的父类或者子类的一种方式。 @@ -70,7 +70,7 @@ let library = [ 在幕后`library` 里存储的媒体项依然是 `Movie` 和 `Song` 类型的,但是,若你迭代它,取出的实例会是 `MediaItem` 类型的,而不是 `Movie` 和 `Song` 类型的。为了让它们作为它们本来的类型工作,你需要检查它们的类型或者向下转换它们的类型到其它类型,就像下面描述的一样。 -## 检查类型 +## 检查类型(Checking Type) 用类型检查操作符(`is`)来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 `true` ,否则返回 `false` 。 @@ -102,17 +102,17 @@ Song`检查item是否为`Song`类型的实例。在循环结束后,`movieCount ## 向下转型(Downcasting) -某类型的一个常量或变量可能在幕后实际上属于一个子类。你可以相信,上面就是这种情况。你可以尝试向下转到它的子类型,用类型转换操作符(`as`) +某类型的一个常量或变量可能在幕后实际上属于一个子类。你可以相信,上面就是这种情况。你可以尝试向下转到它的子类型,用类型检查操作符(`as`) 因为向下转型可能会失败,类型转型操作符带有两种不同形式。可选形式( optional form) `as?` 返回一个你试图下转成的类型的可选值(optional value)。强制形式 `as` 把试图向下转型和强制解包(force-unwraps)结果作为一个混合动作。 -当你不确定向下转型可以成功时,用类型转换的可选形式(`as?`)。可选形式的类型转换总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 `nil` 。这使你能够检查向下转型是否成功。 +当你不确定向下转型可以成功时,用类型检查的可选形式(`as?`)。可选形式的类型检查总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 `nil` 。这使你能够检查向下转型是否成功。 -只有你可以确定向下转型一定会成功时,才使用强制形式。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。 +只有你可以确定向下转型一定会成功时,才使用强制形式。当你试图向下转型为一个不正确的类型时,强制形式的类型检查会触发一个运行时错误。 下面的例子,迭代了`library`里的每一个 `MediaItem` ,并打印出适当的描述。要这样做,`item`需要真正作为`Movie` 或 `Song`的类型来使用。不仅仅是作为 `MediaItem`。为了能够使用`Movie` 或 `Song`的 `director` 或 `artist`属性,这是必要的。 -在这个示例中,数组中的每一个`item`可能是 `Movie` 或 `Song`。 事前你不知道每个`item`的真实类型,所以这里使用可选形式的类型转换 (`as?`)去检查循环里的每次下转。 +在这个示例中,数组中的每一个`item`可能是 `Movie` 或 `Song`。 事前你不知道每个`item`的真实类型,所以这里使用可选形式的类型检查 (`as?`)去检查循环里的每次下转。 ```swift for item in library { @@ -145,7 +145,7 @@ for item in library { 转换没有真的改变实例或它的值。潜在的根本的实例保持不变;只是简单地把它作为它被转换成的类来使用。 -## `Any`和`AnyObject`的类型转换 +## `Any`和`AnyObject`的类型检查 Swift为不确定类型提供了两种特殊类型别名: @@ -160,7 +160,7 @@ Swift为不确定类型提供了两种特殊类型别名: 当需要在工作中使用 Cocoa APIs,它一般接收一个`AnyObject[]`类型的数组,或者说“一个任何对象类型的数组”。这是因为 Objective-C 没有明确的类型化数组。但是,你常常可以确定包含在仅从你知道的 API 信息提供的这样一个数组中的对象的类型。 -在这些情况下,你可以使用强制形式的类型转换(`as`)来下转在数组中的每一项到比 `AnyObject` 更明确的类型,不需要可选解析(optional unwrapping)。 +在这些情况下,你可以使用强制形式的类型检查(`as`)来下转在数组中的每一项到比 `AnyObject` 更明确的类型,不需要可选解析(optional unwrapping)。 下面的示例定义了一个 `AnyObject[]` 类型的数组并填入三个`Movie`类型的实例: @@ -250,4 +250,4 @@ for thing in things { > 注意: -在一个switch语句的case中使用强制形式的类型转换操作符(as, 而不是 as?)来检查和转换到一个明确的类型。在 switch case 语句的内容中这种检查总是安全的。 \ No newline at end of file +在一个switch语句的case中使用强制形式的类型检查操作符(as, 而不是 as?)来检查和转换到一个明确的类型。在 switch case 语句的内容中这种检查总是安全的。 \ No newline at end of file diff --git a/source/chapter3/05_Declarations.md b/source/chapter3/05_Declarations.md index a79c5d76..7b2cc6d2 100644 --- a/source/chapter3/05_Declarations.md +++ b/source/chapter3/05_Declarations.md @@ -1,9 +1,8 @@ -> 翻译:marsprince - -> 校对:numbbbbb, stanzhai +> 翻译:marsprince +> 校对:numbbbbb, stanzhai # 声明 - ----------------- +----------------- 本页包含内容: @@ -64,9 +63,9 @@ 代码块用来将一些声明和控制结构的语句组织在一起。它有如下的形式: - { - `statements` - } +> { +> `statements` +> } 代码块中的语句包括声明,表达式和各种其他类型的语句,它们按照在源码中的出现顺序被依次执行。 @@ -79,13 +78,15 @@ 引入声明使你可以使用在其他文件中声明的内容。引入语句的基本形式是引入整个代码模块;它由import关键字开始,后面 紧跟一个模块名: - import module +> import `module` 你可以提供更多的细节来限制引入的符号,如声明一个特殊的子模块或者在一个模块或子模块中做特殊的声明。(待改进) 当你使用了这些细节后,在当前的程序汇总只有引入的符号是可用的(并不是声明的整个模块)。 - import import kind module.symbol name - import module.submodule +> import `import kind` `module`.`symbol name` +> import `module`.`submodule` + +

> 导入(Import)声明语法 > *导入声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **import** [*导入类型*](..\chapter3\05_Declarations.html#import_kind) _可选_ [*导入路径*](..\chapter3\05_Declarations.html#import_path) @@ -98,7 +99,7 @@ 常量声明可以在你的程序里命名一个常量。常量以关键词let来声明,遵循如下的格式: - let constant name: type = expression +> let `constant name`: `type` = `expression` 当常量的值被给定后,常量就将常量名称和表达式初始值不变的结合在了一起,而且不能更改。 这意味着如果常量以类的形式被初始化,类本身的内容是可以改变的,但是常量和类之间的结合关系是不能改变的。 @@ -107,14 +108,18 @@ 如果常量名是一个元祖形式,元祖中的每一项初始化表达式中都要有对应的值 - let (firstNumber, secondNumber) = (10, 42) +```swift +let (firstNumber, secondNumber) = (10, 42) +``` 在上例中,firstNumber是一个值为10的常量,secnodeName是一个值为42的常量。所有常量都可以独立的使用: - println("The first number is \(firstNumber).") - // prints "The first number is 10." - println("The second number is \(secondNumber).") - // prints "The second number is 42." +```swift +println("The first number is \(firstNumber).") +// prints "The first number is 10." +println("The second number is \(secondNumber).") +// prints "The second number is 42." +``` 类型注释(:type)在常量声明中是一个可选项,它可以用来描述在类型接口(type inference)中找到的类型。 @@ -136,15 +141,14 @@ 变量和属性,存储变量和属性监视,和静态变量属性,有着不同的声明形式。(待改进) 所使用的声明形式取决于变量所声明的范围和你打算声明的变量类型。 ->注意: -> +>注意: 你也可以在协议声明的上下文声明属性,详情参见类型属性声明。 ###存储型变量和存储型属性 下面的形式声明了一个存储型变量或存储型变量属性 - var variable name: type = expression +> var `variable name`: `type` = `expression` 你可以在全局,函数内,或者在类和结构体的声明(context)中使用这种形式来声明一个变量。当变量以这种形式 在全局或者一个函数内被声明时,它代表一个存储型变量。当他在类或者结构体中被声明时,他代表一个存储型变量属性。 @@ -159,14 +163,14 @@ 如下形式声明一个一个存储型变量或存储型属性: - var variable name: type { - get { - statements - } - set(setter name) { - statements - } - } +> var `variable name`: `type` { +> get { +> `statements` +> } +> set(`setter name`) { +> `statements` +> } +> } 你可以在全局,函数体内或者类,结构体,枚举,扩展声明的上下文中使用这种形式的声明。 当变量以这种形式在全局或者一个函数内被声明时,它代表一个计算型变量。当他在类,结构体,枚举,扩展声明的上下文 @@ -187,14 +191,14 @@ setter的初始名为newValue,正如在seter声明速记(shorthand setter decl 你可以用willset和didset监视器来声明一个存储型变量或属性。一个包含监视器的存储型变量或属性按如下的形式声明: - var variable name: type = expression { - willSet(setter name) { - statements - } - didSet(setter name { - statements - } - } +> var `variable name`: `type` = expression { +> willSet(setter name) { +> `statements` +> } +> didSet(`setter name`) { +> `statements` +> } +> } 你可以在全局,函数体内或者类,结构体,枚举,扩展声明的上下文中使用这种形式的声明。 当变量以这种形式在全局或者一个函数内被声明时,监视器代表一个存储型变量监视器; @@ -253,7 +257,7 @@ class关键字用来声明类的计算型属性。static关键字用来声明类 类型别名的声明可以在你的程序里为一个已存在的类型声明一个别名。类型的别名声明以关键字typealias开始,遵循如下的 形式: - typealias name = existing type +> `typealias name` = `existing type` 当一个类型被别名被声明后,你可以在你程序的任何地方使用别名来代替已存在的类型。已存在的类型可以是已经被命名的 类型或者是混合类型。类型的别名不产生新的类型,它只是简单的和已存在的类型做名称替换。 @@ -272,15 +276,15 @@ class关键字用来声明类的计算型属性。static关键字用来声明类 你可以使用函数声明在你的程序里引入新的函数。函数可以在类的上下文,结构体,枚举,或者作为方法的协议中被声明。 函数声明使用关键字func,遵循如下的形式: - func function name(parameters) -> return type { - statements - } +> func `function name`(`parameters`) -> `return type` { +> `statements` +> } 如果函数不返回任何值,返回类型可以被忽略,如下所示: - func function name(parameters) { - statements - } +> func `function name`(`parameters`) { +> `statements` +> } 每个参数的类型都要标明,它们不能被推断出来。初始时函数的参数是常值。在这些参数前面添加var使它们成为变量, 作用域内任何对变量的改变只在函数体内有效,或者用inout使的这些改变可以在调用域内生效。 @@ -295,29 +299,33 @@ class关键字用来声明类的计算型属性。static关键字用来声明类 函数的参数是一个以逗号分隔的列表 。函数调用是的变量顺序必须和函数声明时的参数顺序一致。 最简单的参数列表有着如下的形式: - parameter name: parameter type +> `parameter name`: `parameter type` 对于函数参数来讲,参数名在函数体内被使用,而不是在函数调用时使用。对于方法参数,参数名在函数体内被使用, 同时也在方法被调用时作为标签被使用。该方法的第一个参数名仅仅在函数体内被使用,就像函数的参数一样,举例来讲: - func f(x: Int, y: String) -> String { - return y + String(x) - } - f(7, "hello") // x and y have no name +```swift +func f(x: Int, y: String) -> String { + return y + String(x) +} +f(7, "hello") // x and y have no name +``` - class C { - func f(x: Int, y: String) -> String { - return y + String(x) - } +```swift +class C { + func f(x: Int, y: String) -> String { + return y + String(x) } - let c = C() - c.f(7, y: "hello") // x没有名称,y有名称 +} +let c = C() +c.f(7, y: "hello") // x没有名称,y有名称 +``` 你可以按如下的形式,重写参数名被使用的过程: - external parameter name local parameter name: parameter type - #parameter name: parameter type - _ local parameter name: parameter type +> `external parameter name` `local parameter name`: `parameter type` +> #`parameter name`: `parameter type` +> _ `local parameter name`: `parameter type` 在本地参数前命名的第二名称(second name)使得参数有一个扩展名。且不同于本地的参数名。 扩展参数名在函数被调用时必须被使用。对应的参数在方法或函数被调用时必须有扩展名 。 @@ -331,9 +339,9 @@ class关键字用来声明类的计算型属性。static关键字用来声明类 参数可以被忽略,值可以是变化的,并且提供一个初始值,这种方法有着如下的形式: - _ : <#parameter type#. - parameter name: parameter type... - parameter name: parameter type = default argument value +> _ : <#parameter type#. +> `parameter name`: `parameter type`... +> `parameter name`: `parameter type` = `default argument value` 以强调符(_)命名的参数明确的在函数体内不能被访问。 @@ -358,23 +366,27 @@ f()和f(x:7)都是只有一个变量x的函数的有效调用,但是f(7)是非 柯里化函数或方法有着如下的形式: - func function name(parameters)(parameters) -> return type { - statements - } +> func `function name`(`parameters`)(`parameters`) -> `return type` { +> `statements` +> } 以这种形式定义的函数的返回值是另一个函数。举例来说,下面的两个声明时等价的: - func addTwoNumbers(a: Int)(b: Int) -> Int { +```swift +func addTwoNumbers(a: Int)(b: Int) -> Int { + return a + b +} +func addTwoNumbers(a: Int) -> (Int -> Int) { + func addTheSecondNumber(b: Int) -> Int { return a + b } - func addTwoNumbers(a: Int) -> (Int -> Int) { - func addTheSecondNumber(b: Int) -> Int { - return a + b - } - return addTheSecondNumber - } + return addTheSecondNumber +} +``` - addTwoNumbers(4)(5) // Returns 9 +```swift +addTwoNumbers(4)(5) // Returns 9 +``` 多级柯里化应用如下 @@ -416,10 +428,10 @@ f()和f(x:7)都是只有一个变量x的函数的有效调用,但是f(7)是非 如下的形式声明了一个包含任意类型枚举时间的枚举变量 - enum enumeration name { - case enumeration case 1 - case enumeration case 2(associated value types) - } +> enum `enumeration name` { +> case `enumeration case 1` +> case `enumeration case 2`(`associated value types`) +> } 这种形式的枚举声明在其他语言中有时被叫做可识别联合(discrinminated)。 @@ -431,10 +443,10 @@ f()和f(x:7)都是只有一个变量x的函数的有效调用,但是f(7)是非 以下的形式声明了一个包含相同基础类型的枚举事件的枚举: - enum enumeration name: raw value type { - case enumeration case 1 = raw value 1 - case enumeration case 2 = raw value 2 - } +> enum `enumeration name`: `raw value type` { +> case `enumeration case 1` = `raw value 1` +> case `enumeration case 2` = `raw value 2` +> } 在这种形式中,每一个事件块由case关键字开始,后面紧接着一个或多个以逗号分隔的枚举事件。和第一种形式的枚举 事件不同,这种形式的枚举事件包含一个同类型的基础值,叫做原始值(raw value)。这些值的类型在原始值类型(raw value type) @@ -443,9 +455,11 @@ f()和f(x:7)都是只有一个变量x的函数的有效调用,但是f(7)是非 每一个事件必须有唯一的名字,必须有一个唯一的初始值。如果初始值类型被指定为int,则不必为事件显式的指定值, 它们会隐式的被标为值0,1,2等。每一个没有被赋值的Int类型时间会隐式的赋予一个初始值,它们是自动递增的。 - num ExampleEnum: Int { - case A, B, C = 5, D - } +```swift +num ExampleEnum: Int { + case A, B, C = 5, D +} +``` 在上面的例子中,ExampleEnum.A的值是0,ExampleEnum.B的值是。因为ExampleEnum.C的值被显式的设定为5,因此 ExampleEnum.D的值会自动增长为6. @@ -485,9 +499,9 @@ ExampleEnum.D的值会自动增长为6. 使用结构体声明可以在你的程序里引入一个结构体类型。结构体声明使用struct关键字,遵循如下的形式: - struct structure name: adopted protocols { - declarations - } +> struct `structure name`: `adopted protocols` { +> `declarations` +> } 结构体内包含零或多个声明。这些声明可以包括存储型和计算型属性,静态属性,实例方法,静态方法,构造器, 类型别名,甚至其他结构体,类,和枚举声明。结构体声明不能包含析构器或者协议声明。详细讨论和包含多种结构体 @@ -522,9 +536,9 @@ ExampleEnum.D的值会自动增长为6. 你可以在你的程序中使用类声明来引入一个类。类声明使用关键字class,遵循如下的形式: - class class name: superclass, adopted protocols { - declarations - } +> class `class name`: `superclass`, `adopted protocols` { +> `declarations` +> } 一个类内包含零或多个声明。这些声明可以包括存储型和计算型属性,实例方法,类方法,构造器,单独的析构器方法, 类型别名,甚至其他结构体,类,和枚举声明。类声明不能包含协议声明。详细讨论和包含多种类声明的实例,参见类和 @@ -543,9 +557,8 @@ ExampleEnum.D的值会自动增长为6. 有两种方法来创建已声明的类的实例: --调用类的一个构造器,参见构造器(initializers)。 - --如果没有声明构造器,而且类的所有属性都被赋予了初始值,调用类的默认构造器,参见默认构造器(default initializers). +- 调用类的一个构造器,参见构造器(initializers)。 +- 如果没有声明构造器,而且类的所有属性都被赋予了初始值,调用类的默认构造器,参见默认构造器(default initializers). 类实例属性可以用点(.)来获得,详情参见获得属性(Accessing Properties)一节。 @@ -564,18 +577,15 @@ ExampleEnum.D的值会自动增长为6. 一个协议声明为你的程序引入一个命名了的协议类型。协议声明使用 `protocol` 关键词来进行声明并有下面这样的形式: -```javascript -protocol protocol name: inherited protocols { - protocol member declarations -} -``` +> protocol `protocol name`: `inherited protocols` { +> `protocol member declarations` +> } 协议的主体包含零或多个协议成员声明,这些成员描述了任何采用该协议必须满足的一致性要求。特别的,一个协议可以声明必须实现某些属性、方法、初始化程序及附属脚本的一致性类型。协议也可以声明专用种类的类型别名,叫做关联类型,它可以指定协议的不同声明之间的关系。协议成员声明会在下面的详情里进行讨论。 协议类型可以从很多其它协议那继承。当一个协议类型从其它协议那继承的时候,来自其它协议的所有要求就集合了,而且从当前协议继承的任何类型必须符合所有的这些要求。对于如何使用协议继承的例子,查看[协议继承](../chapter2/21_Protocols.html#protocol_inheritance) -> 注意: -> +> 注意: 你也可以使用协议合成类型集合多个协议的一致性要求,详情参见[协议合成类型](../chapter3/03_Types.html#protocol_composition_type)和[协议合成](../chapter2/21_Protocols.html#protocol_composition) 你可以通过采用在类型的扩展声明中的协议来为之前声明的类型添加协议一致性。在扩展中你必须实现所有采用协议的要求。如果该类型已经实现了所有的要求,你可以让这个扩展声明的主题留空。 @@ -584,8 +594,7 @@ protocol protocol name: inherited protocols { 为了限制协议的采用仅仅针对类类型,需要使用`class_protocol`属性标记整个协议声明。任意继承自标记有`class_protocol`属性协议的协议都可以智能地仅能被类类型采用。 ->注意: -> +>注意: 如果协议已经用`object`属性标记了,`class_protocol`属性就隐性地应用于该协议;没有必要再明确地使用`class_protocol`属性来标记该协议了。 协议是命名的类型,因此它们可以以另一个命名类型出现在你代码的所有地方,就像[协议类型](../chapter2/21_Protocols.html#protocols_as_types)里讨论的那样。然而你不能构造一个协议的实例,因为协议实际上不提供它们指定的要求的实现。 @@ -608,7 +617,7 @@ protocol protocol name: inherited protocols { 协议声明了一致性类型必须在协议声明的主体里通过引入一个协议属性声明来实现一个属性。协议属性声明有一种特殊的类型声明形式: - var property name: type { get set } +> var `property name`: `type` { get set } 同其它协议成员声明一样,这些属性声明仅仅针对符合该协议的类型声明了`getter`和`setter`要求。结果就是你不需要在协议里它被声明的地方实现`getter`和`setter`。 @@ -649,7 +658,7 @@ protocol protocol name: inherited protocols { 协议声明了一致性类型必须在协议声明的主体里通过引入一个协议附属脚本声明来实现一个附属脚本。协议属性声明 对附属脚本声明有一个特殊的形式: - subscript (parameters) -> return type { get set } +> subscript (`parameters`) -> `return type` { get set } 附属脚本声明只为和协议一致的类型声明了必需的最小数量的的getter和setter。如果附属脚本申明包含get和set关键字, 一致的类型也必须有一个getter和setter语句。如果附属脚本声明值包含get关键字,一致的类型必须至少包含一个 @@ -679,9 +688,9 @@ getter语句,可以选择是否包含setter语句。 如下的形式声明了结构体,枚举和类的指定构造器: - init(parameters) { - statements - } +> init(`parameters`) { +> `statements` +> } 类的指定构造器将类的所有属性直接初始化。如果类有超类,它不能调用该类的其他构造器,它只能调用超类的一个 指定构造器。如果该类从它的超类处继承了任何属性,这些属性在当前类内被赋值或修饰时,必须带哦用一个超类的 @@ -693,9 +702,9 @@ getter语句,可以选择是否包含setter语句。 以关键字convenience来声明一个类的便利构造器: - convenience init(parameters) { - statements - } +> convenience init(`parameters`) { +> `statements` +> } 便利构造器可以将初始化过程委托给另一个便利构造器或类的一个指定构造器。这意味着,类的初始化过程必须 以一个将所有类属性完全初始化的指定构造器的调用作为结束。便利构造器不能调用超类的构造器。 @@ -717,9 +726,9 @@ overrride关键字。 析构声明为类声明了一个析构器。析构器没有参数,遵循如下的格式: - deinit { - statements - } +> deinit { +> `statements` +> } 当类没有任何语句时将要被释放时,析构器会自动的被调用。析构器在类的声明体内只能被声明一次——但是不能在 类的扩展声明内,每个类最多只能有一个。 @@ -738,9 +747,9 @@ overrride关键字。 扩展声明用于扩展一个现存的类,结构体,枚举的行为。扩展声明以关键字extension开始,遵循如下的规则: - extension type: adopted protocols { - declarations - } +> extension `type`: `adopted protocols` { +> `declarations` +> } 一个扩展声明体包括零个或多个声明。这些声明可以包括计算型属性,计算型静态属性,实例方法,静态和类方法,构造器, 附属脚本声明,甚至其他结构体,类,和枚举声明。扩展声明不能包含析构器,协议声明,存储型属性,属性监测器或其他 @@ -762,14 +771,15 @@ type-inheritance-clause是一个只包含协议列表的扩展声明。 ##附属脚本声明(translated by 林) 附属脚本用于向特定类型添加附属脚本支持,通常为访问集合,列表和序列的元素时提供语法便利。附属脚本声明使用关键字`subscript`,声明形式如下: + > subscript (`parameter`) -> (return type){ - get{ - `statements` - } - set(`setter name`){ - `statements` - } -} +> get{ +> `statements` +> } +> set(`setter name`){ +> `statements` +> } +> } 附属脚本声明只能在类,结构体,枚举,扩展和协议声明的上下文进行声明。 @@ -790,7 +800,7 @@ setter的名字和封闭的括号是可选的。如果使用了setter名称, > *附属脚本声明* → [*附属脚本头(Head)*](..\chapter3\05_Declarations.html#subscript_head) [*附属脚本结果(Result)*](..\chapter3\05_Declarations.html#subscript_result) [*getter-setter块*](..\chapter3\05_Declarations.html#getter_setter_block) > *附属脚本声明* → [*附属脚本头(Head)*](..\chapter3\05_Declarations.html#subscript_head) [*附属脚本结果(Result)*](..\chapter3\05_Declarations.html#subscript_result) [*getter-setter关键字(Keyword)块*](..\chapter3\05_Declarations.html#getter_setter_keyword_block) > *附属脚本头(Head)* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **subscript** [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) -> *附属脚本结果(Result)* → **->** [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type) +> *附属脚本结果(Result)* → **->** [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type) ##运算符声明(translated by 林) @@ -800,10 +810,10 @@ setter的名字和封闭的括号是可选的。如果使用了setter名称, 运算符声明有三种基本形式,每种缀性各一种。运算符的缀性通过在`operator`和运算符之间添加上下文关键字`infix`,`prefix`或`postfix`来指定。每种形式中,运算符的名字只能包含[Operators](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-XID_871)中定义的运算符字符。 下面的这种形式声明了一个新的中缀运算符: -> operator infix `operator name`{ - precedence `precedence level` - associativity `associativity` - } +> operator infix `operator name`{ +> previewprecedence `precedence level` +> associativity `associativity` +> } _中缀_运算符是二元运算符,它可以被置于两个操作数之间,比如表达式`1 + 2` 中的加法运算符(`+`)。 @@ -817,7 +827,7 @@ _中缀_运算符是二元运算符,它可以被置于两个操作数之间, 声明时不指定任何优先级或结合性的中缀运算符,它们的优先级会被初始化为100,结合性被初始化为`none`。 下面的这种形式声明了一个新的前缀运算符: -> operator prefix `operator name`{} +> operator prefix `operator name`{} 紧跟在操作数前边的_前缀运算符(prefix operator)_是一元运算符,例如表达式`++i`中的前缀递增运算符(`++`)。 @@ -825,7 +835,7 @@ _中缀_运算符是二元运算符,它可以被置于两个操作数之间, 下面的这种形式声明了一个新的后缀运算符: -> operator postfix `operator name`{} +> operator postfix `operator name`{} 紧跟在操作数后边的_后缀运算符(postfix operator)_是一元运算符,例如表达式`i++`中的前缀递增运算符(`++`)。 @@ -842,4 +852,4 @@ _中缀_运算符是二元运算符,它可以被置于两个操作数之间, > *优先级子句* → **precedence** [*优先级水平*](..\chapter3\05_Declarations.html#precedence_level) > *优先级水平* → 数值 0 到 255 > *结和性子句* → **associativity** [*结和性*](..\chapter3\05_Declarations.html#associativity) -> *结和性* → **left** | **right** | **none** \ No newline at end of file +> *结和性* → **left** | **right** | **none**