@ -1,6 +1,6 @@
|
||||
# Swift 初见
|
||||
|
||||
通常来说,编程语言教程中的第一个程序应该在屏幕上打印 “Hello, world”。在 Swift 中,可以用一行代码实现:
|
||||
通常来说,编程语言教程中的第一个程序应该在屏幕上打印“Hello, world”。在 Swift 中,可以用一行代码实现:
|
||||
|
||||
```swift
|
||||
print("Hello, world!")
|
||||
|
||||
@ -124,7 +124,7 @@ var anotherEmptyString = String() // 初始化方法
|
||||
if emptyString.isEmpty {
|
||||
print("Nothing to see here")
|
||||
}
|
||||
// 打印输出:"Nothing to see here"
|
||||
// 打印输出:“Nothing to see here”
|
||||
```
|
||||
|
||||
<a name="string_mutability"></a>
|
||||
@ -185,7 +185,7 @@ let exclamationMark: Character = "!"
|
||||
let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
|
||||
let catString = String(catCharacters)
|
||||
print(catString)
|
||||
// 打印输出:"Cat!🐱"
|
||||
// 打印输出:“Cat!🐱”
|
||||
```
|
||||
|
||||
<a name="concatenating_strings_and_characters"></a>
|
||||
@ -326,7 +326,7 @@ let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
|
||||
```swift
|
||||
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
|
||||
print("unusualMenagerie has \(unusualMenagerie.count) characters")
|
||||
// 打印输出 "unusualMenagerie has 40 characters"
|
||||
// 打印输出“unusualMenagerie has 40 characters”
|
||||
```
|
||||
|
||||
注意在 Swift 中,使用可拓展的字符群集作为 `Character` 值来连接或改变字符串时,并不一定会更改字符串的字符数量。
|
||||
@ -336,12 +336,12 @@ print("unusualMenagerie has \(unusualMenagerie.count) characters")
|
||||
```swift
|
||||
var word = "cafe"
|
||||
print("the number of characters in \(word) is \(word.count)")
|
||||
// 打印输出 "the number of characters in cafe is 4"
|
||||
// 打印输出“the number of characters in cafe is 4”
|
||||
|
||||
word += "\u{301}" // 拼接一个重音,U+0301
|
||||
|
||||
print("the number of characters in \(word) is \(word.count)")
|
||||
// 打印输出 "the number of characters in café is 4"
|
||||
// 打印输出“the number of characters in café is 4”
|
||||
```
|
||||
|
||||
> 注意
|
||||
@ -394,7 +394,7 @@ greeting.index(after: endIndex) // error
|
||||
for index in greeting.indices {
|
||||
print("\(greeting[index]) ", terminator: "")
|
||||
}
|
||||
// 打印输出 "G u t e n T a g ! "
|
||||
// 打印输出“G u t e n T a g ! ”
|
||||
```
|
||||
|
||||
> 注意
|
||||
@ -471,7 +471,7 @@ let sameQuotation = "We're a lot alike, you and I."
|
||||
if quotation == sameQuotation {
|
||||
print("These two strings are considered equal")
|
||||
}
|
||||
// 打印输出 "These two strings are considered equal"
|
||||
// 打印输出“These two strings are considered equal”
|
||||
```
|
||||
|
||||
如果两个字符串(或者两个字符)的可扩展的字形群集是标准相等,那就认为它们是相等的。只要可扩展的字形群集有同样的语言意义和外观则认为它们标准相等,即使它们是由不同的 Unicode 标量构成。
|
||||
@ -488,7 +488,7 @@ let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"
|
||||
if eAcuteQuestion == combinedEAcuteQuestion {
|
||||
print("These two strings are considered equal")
|
||||
}
|
||||
// 打印输出 "These two strings are considered equal"
|
||||
// 打印输出“These two strings are considered equal”
|
||||
```
|
||||
|
||||
相反,英语中的 `LATIN CAPITAL LETTER A`(`U+0041`,或者 `A`)不等于俄语中的 `CYRILLIC CAPITAL LETTER A`(`U+0410`,或者 `A`)。两个字符看着是一样的,但却有不同的语言意义:
|
||||
@ -501,7 +501,7 @@ let cyrillicCapitalLetterA: Character = "\u{0410}"
|
||||
if latinCapitalLetterA != cyrillicCapitalLetterA {
|
||||
print("These two characters are not equivalent")
|
||||
}
|
||||
// 打印 "These two characters are not equivalent"
|
||||
// 打印“These two characters are not equivalent”
|
||||
```
|
||||
|
||||
> 注意
|
||||
@ -541,7 +541,7 @@ for scene in romeoAndJuliet {
|
||||
}
|
||||
}
|
||||
print("There are \(act1SceneCount) scenes in Act 1")
|
||||
// 打印输出 "There are 5 scenes in Act 1"
|
||||
// 打印输出“There are 5 scenes in Act 1”
|
||||
```
|
||||
|
||||
相似地,你可以用 `hasSuffix(_:)` 方法来计算发生在不同地方的场景数:
|
||||
@ -557,7 +557,7 @@ for scene in romeoAndJuliet {
|
||||
}
|
||||
}
|
||||
print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
|
||||
// 打印输出 "6 mansion scenes; 2 cell scenes"
|
||||
// 打印输出“6 mansion scenes; 2 cell scenes”
|
||||
```
|
||||
|
||||
> 注意
|
||||
|
||||
@ -41,7 +41,7 @@ Swift 语言中的 `Arrays`、`Sets` 和 `Dictionaries` 中存储的数据值类
|
||||
```swift
|
||||
var someInts = [Int]()
|
||||
print("someInts is of type [Int] with \(someInts.count) items.")
|
||||
// 打印 "someInts is of type [Int] with 0 items."
|
||||
// 打印“someInts is of type [Int] with 0 items.”
|
||||
```
|
||||
|
||||
注意,通过构造函数的类型,`someInts` 的值类型被推断为 `[Int]`。
|
||||
@ -128,7 +128,7 @@ if shoppingList.isEmpty {
|
||||
} else {
|
||||
print("The shopping list is not empty.")
|
||||
}
|
||||
// 打印 "The shopping list is not empty."(shoppinglist 不是空的)
|
||||
// 打印“The shopping list is not empty.”(shoppinglist 不是空的)
|
||||
```
|
||||
|
||||
也可以使用 `append(_:)` 方法在数组后面添加新的数据项:
|
||||
@ -288,7 +288,7 @@ Swift 中的 `Set` 类型被写为 `Set<Element>`,这里的 `Element` 表示 `
|
||||
```swift
|
||||
var letters = Set<Character>()
|
||||
print("letters is of type Set<Character> with \(letters.count) items.")
|
||||
// 打印 "letters is of type Set<Character> with 0 items."
|
||||
// 打印“letters is of type Set<Character> with 0 items.”
|
||||
```
|
||||
|
||||
> 注意
|
||||
@ -339,7 +339,7 @@ var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
|
||||
|
||||
```swift
|
||||
print("I have \(favoriteGenres.count) favorite music genres.")
|
||||
// 打印 "I have 3 favorite music genres."
|
||||
// 打印“I have 3 favorite music genres.”
|
||||
```
|
||||
|
||||
使用布尔属性 `isEmpty` 作为一个缩写形式去检查 `count` 属性是否为 `0`:
|
||||
@ -350,7 +350,7 @@ if favoriteGenres.isEmpty {
|
||||
} else {
|
||||
print("I have particular music preferences.")
|
||||
}
|
||||
// 打印 "I have particular music preferences."
|
||||
// 打印“I have particular music preferences.”
|
||||
```
|
||||
|
||||
你可以通过调用 `Set` 的 `insert(_:)` 方法来添加一个新元素:
|
||||
@ -368,7 +368,7 @@ if let removedGenre = favoriteGenres.remove("Rock") {
|
||||
} else {
|
||||
print("I never much cared for that.")
|
||||
}
|
||||
// 打印 "Rock? I'm over it."
|
||||
// 打印“Rock? I'm over it.”
|
||||
```
|
||||
|
||||
使用 `contains(_:)` 方法去检查 `Set` 中是否包含一个特定的值:
|
||||
@ -379,7 +379,7 @@ if favoriteGenres.contains("Funk") {
|
||||
} else {
|
||||
print("It's too funky in here.")
|
||||
}
|
||||
// 打印 "It's too funky in here."
|
||||
// 打印“It's too funky in here.”
|
||||
```
|
||||
|
||||
<a name="iterating_over_a_set"></a>
|
||||
@ -555,7 +555,7 @@ var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
|
||||
|
||||
```swift
|
||||
print("The dictionary of airports contains \(airports.count) items.")
|
||||
// 打印 "The dictionary of airports contains 2 items."(这个字典有两个数据项)
|
||||
// 打印“The dictionary of airports contains 2 items.”(这个字典有两个数据项)
|
||||
```
|
||||
|
||||
使用布尔属性 `isEmpty` 作为一个缩写形式去检查 `count` 属性是否为 `0`:
|
||||
@ -566,7 +566,7 @@ if airports.isEmpty {
|
||||
} else {
|
||||
print("The airports dictionary is not empty.")
|
||||
}
|
||||
// 打印 "The airports dictionary is not empty."
|
||||
// 打印“The airports dictionary is not empty.”
|
||||
```
|
||||
|
||||
我们也可以在字典中使用下标语法来添加新的数据项。可以使用一个恰当类型的键作为下标索引,并且分配恰当类型的新值:
|
||||
@ -604,7 +604,7 @@ if let airportName = airports["DUB"] {
|
||||
} else {
|
||||
print("That airport is not in the airports dictionary.")
|
||||
}
|
||||
// 打印 "The name of the airport is Dublin Airport."
|
||||
// 打印“The name of the airport is Dublin Airport.”
|
||||
```
|
||||
|
||||
我们还可以使用下标语法来通过给某个键的对应值赋值为 `nil` 来从字典里移除一个键值对:
|
||||
|
||||
@ -28,9 +28,9 @@ func greet(person: String) -> String {
|
||||
|
||||
```swift
|
||||
print(greet(person: "Anna"))
|
||||
// 打印 "Hello, Anna!"
|
||||
// 打印“Hello, Anna!”
|
||||
print(greet(person: "Brian"))
|
||||
// 打印 "Hello, Brian!"
|
||||
// 打印“Hello, Brian!”
|
||||
```
|
||||
|
||||
调用 `greet(person:)` 函数时,在圆括号中传给它一个 `String` 类型的实参,例如 `greet(person: "Anna")`。正如上面所示,因为这个函数返回一个 `String` 类型的值,所以 `greet` 可以被包含在 `print(_:separator:terminator:)` 的调用中,用来输出这个函数的返回值。
|
||||
@ -50,7 +50,7 @@ func greetAgain(person: String) -> String {
|
||||
return "Hello again, " + person + "!"
|
||||
}
|
||||
print(greetAgain(person: "Anna"))
|
||||
// 打印 "Hello again, Anna!"
|
||||
// 打印“Hello again, Anna!”
|
||||
```
|
||||
|
||||
<a name="Function_Parameters_and_Return_Values"></a>
|
||||
@ -68,7 +68,7 @@ func sayHelloWorld() -> String {
|
||||
return "hello, world"
|
||||
}
|
||||
print(sayHelloWorld())
|
||||
// 打印 "hello, world"
|
||||
// 打印“hello, world”
|
||||
```
|
||||
|
||||
尽管这个函数没有参数,但是定义中在函数名后还是需要一对圆括号。当被调用时,也需要在函数名后写一对圆括号。
|
||||
@ -89,7 +89,7 @@ func greet(person: String, alreadyGreeted: Bool) -> String {
|
||||
}
|
||||
}
|
||||
print(greet(person: "Tim", alreadyGreeted: true))
|
||||
// 打印 "Hello again, Tim!"
|
||||
// 打印“Hello again, Tim!”
|
||||
```
|
||||
|
||||
你可以通过在括号内使用逗号分隔来传递一个 `String` 参数值和一个标识为 `alreadyGreeted` 的 `Bool` 值,来调用 `greet(person:alreadyGreeted:)` 函数。注意这个函数和上面 `greet(person:)` 是不同的。虽然它们都有着同样的名字 `greet`,但是 `greet(person:alreadyGreeted:)` 函数需要两个参数,而 `greet(person:)` 只需要一个参数。
|
||||
@ -104,7 +104,7 @@ func greet(person: String) {
|
||||
print("Hello, \(person)!")
|
||||
}
|
||||
greet(person: "Dave")
|
||||
// 打印 "Hello, Dave!"
|
||||
// 打印“Hello, Dave!”
|
||||
```
|
||||
|
||||
因为这个函数不需要返回值,所以这个函数的定义中没有返回箭头(->)和返回类型。
|
||||
@ -124,9 +124,9 @@ func printWithoutCounting(string: String) {
|
||||
let _ = printAndCount(string: string)
|
||||
}
|
||||
printAndCount(string: "hello, world")
|
||||
// 打印 "hello, world" 并且返回值 12
|
||||
// 打印“hello, world”,并且返回值 12
|
||||
printWithoutCounting(string: "hello, world")
|
||||
// 打印 "hello, world" 但是没有返回任何值
|
||||
// 打印“hello, world”,但是没有返回任何值
|
||||
```
|
||||
|
||||
第一个函数 `printAndCount(string:)`,输出一个字符串并返回 `Int` 类型的字符数。第二个函数 `printWithoutCounting(string:)` 调用了第一个函数,但是忽略了它的返回值。当第二个函数被调用时,消息依然会由第一个函数输出,但是返回值不会被用到。
|
||||
@ -166,7 +166,7 @@ func minMax(array: [Int]) -> (min: Int, max: Int) {
|
||||
```swift
|
||||
let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
|
||||
print("min is \(bounds.min) and max is \(bounds.max)")
|
||||
// 打印 "min is -6 and max is 109"
|
||||
// 打印“min is -6 and max is 109”
|
||||
```
|
||||
|
||||
需要注意的是,元组的成员不需要在元组从函数中返回时命名,因为它们的名字已经在函数返回类型中指定了。
|
||||
@ -206,7 +206,7 @@ func minMax(array: [Int]) -> (min: Int, max: Int)? {
|
||||
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
|
||||
print("min is \(bounds.min) and max is \(bounds.max)")
|
||||
}
|
||||
// 打印 "min is -6 and max is 109"
|
||||
// 打印“min is -6 and max is 109”
|
||||
```
|
||||
|
||||
<a name="Function_Argument_Labels_and_Parameter_Names"></a>
|
||||
@ -241,7 +241,7 @@ func greet(person: String, from hometown: String) -> String {
|
||||
return "Hello \(person)! Glad you could visit from \(hometown)."
|
||||
}
|
||||
print(greet(person: "Bill", from: "Cupertino"))
|
||||
// 打印 "Hello Bill! Glad you could visit from Cupertino."
|
||||
// 打印“Hello Bill! Glad you could visit from Cupertino.”
|
||||
```
|
||||
|
||||
参数标签的使用能够让一个函数在调用时更有表达力,更类似自然语言,并且仍保持了函数内部的可读性以及清晰的意图。
|
||||
@ -334,7 +334,7 @@ var someInt = 3
|
||||
var anotherInt = 107
|
||||
swapTwoInts(&someInt, &anotherInt)
|
||||
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
|
||||
// 打印 "someInt is now 107, and anotherInt is now 3"
|
||||
// 打印“someInt is now 107, and anotherInt is now 3”
|
||||
```
|
||||
|
||||
从上面这个例子中,我们可以看到 `someInt` 和 `anotherInt` 的原始值在 `swapTwoInts(_:_:)` 函数中被修改,尽管它们的定义在函数体外。
|
||||
@ -424,7 +424,7 @@ func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
|
||||
print("Result: \(mathFunction(a, b))")
|
||||
}
|
||||
printMathResult(addTwoInts, 3, 5)
|
||||
// 打印 "Result: 8"
|
||||
// 打印“Result: 8”
|
||||
```
|
||||
|
||||
这个例子定义了 `printMathResult(_:_:_:)` 函数,它有三个参数:第一个参数叫 `mathFunction`,类型是 `(Int, Int) -> Int`,你可以传入任何这种类型的函数;第二个和第三个参数叫 `a` 和 `b`,它们的类型都是 `Int`,这两个值作为已给出的函数的输入值。
|
||||
|
||||
@ -351,11 +351,11 @@ class SomeClass {
|
||||
let instance = SomeClass()
|
||||
instance.doSomething()
|
||||
print(instance.x)
|
||||
// 打印出 "200"
|
||||
// 打印出“200”
|
||||
|
||||
completionHandlers.first?()
|
||||
print(instance.x)
|
||||
// 打印出 "100"
|
||||
// 打印出“100”
|
||||
```
|
||||
|
||||
<a name="autoclosures"></a>
|
||||
@ -370,16 +370,16 @@ print(instance.x)
|
||||
```swift
|
||||
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
|
||||
print(customersInLine.count)
|
||||
// 打印出 "5"
|
||||
// 打印出“5”
|
||||
|
||||
let customerProvider = { customersInLine.remove(at: 0) }
|
||||
print(customersInLine.count)
|
||||
// 打印出 "5"
|
||||
// 打印出“5”
|
||||
|
||||
print("Now serving \(customerProvider())!")
|
||||
// Prints "Now serving Chris!"
|
||||
print(customersInLine.count)
|
||||
// 打印出 "4"
|
||||
// 打印出“4”
|
||||
```
|
||||
|
||||
尽管在闭包的代码中,`customersInLine` 的第一个元素被移除了,不过在闭包被调用之前,这个元素是不会被移除的。如果这个闭包永远不被调用,那么在闭包里面的表达式将永远不会执行,那意味着列表中的元素永远不会被移除。请注意,`customerProvider` 的类型不是 `String`,而是 `() -> String`,一个没有参数且返回值为 `String` 的函数。
|
||||
@ -392,7 +392,7 @@ func serve(customer customerProvider: () -> String) {
|
||||
print("Now serving \(customerProvider())!")
|
||||
}
|
||||
serve(customer: { customersInLine.remove(at: 0) } )
|
||||
// 打印出 "Now serving Alex!"
|
||||
// 打印出“Now serving Alex!”
|
||||
```
|
||||
|
||||
上面的 `serve(customer:)` 函数接受一个返回顾客名字的显式的闭包。下面这个版本的 `serve(customer:)` 完成了相同的操作,不过它并没有接受一个显式的闭包,而是通过将参数标记为 `@autoclosure` 来接收一个自动闭包。现在你可以将该函数当作接受 `String` 类型参数(而非闭包)的函数来调用。`customerProvider` 参数将自动转化为一个闭包,因为该参数被标记了 `@autoclosure` 特性。
|
||||
@ -403,7 +403,7 @@ func serve(customer customerProvider: @autoclosure () -> String) {
|
||||
print("Now serving \(customerProvider())!")
|
||||
}
|
||||
serve(customer: customersInLine.remove(at: 0))
|
||||
// 打印 "Now serving Ewa!"
|
||||
// 打印“Now serving Ewa!”
|
||||
```
|
||||
|
||||
> 注意
|
||||
@ -422,12 +422,12 @@ collectCustomerProviders(customersInLine.remove(at: 0))
|
||||
collectCustomerProviders(customersInLine.remove(at: 0))
|
||||
|
||||
print("Collected \(customerProviders.count) closures.")
|
||||
// 打印 "Collected 2 closures."
|
||||
// 打印“Collected 2 closures.”
|
||||
for customerProvider in customerProviders {
|
||||
print("Now serving \(customerProvider())!")
|
||||
}
|
||||
// 打印 "Now serving Barry!"
|
||||
// 打印 "Now serving Daniella!"
|
||||
// 打印“Now serving Barry!”
|
||||
// 打印“Now serving Daniella!”
|
||||
```
|
||||
|
||||
在上面的代码中,`collectCustomerProviders(_:)` 函数并没有调用传入的 `customerProvider` 闭包,而是将闭包追加到了 `customerProviders` 数组中。这个数组定义在函数作用域范围外,这意味着数组内的闭包能够在函数返回之后被调用。因此,`customerProvider` 参数必须允许“逃逸”出函数作用域。
|
||||
|
||||
@ -77,7 +77,7 @@ case .east:
|
||||
case .west:
|
||||
print("Where the skies are blue")
|
||||
}
|
||||
// 打印 "Watch out for penguins”
|
||||
// 打印“Watch out for penguins”
|
||||
```
|
||||
|
||||
你可以这样理解这段代码:
|
||||
@ -98,7 +98,7 @@ case .earth:
|
||||
default:
|
||||
print("Not a safe place for humans")
|
||||
}
|
||||
// 打印 "Mostly harmless”
|
||||
// 打印“Mostly harmless”
|
||||
```
|
||||
|
||||
<a name="iterating over enumeration cases"></a>
|
||||
@ -114,7 +114,7 @@ enum Beverage: CaseIterable {
|
||||
}
|
||||
let numberOfChoices = Beverage.allCases.count
|
||||
print("\(numberOfChoices) beverages available")
|
||||
// 打印 "3 beverages available"
|
||||
// 打印“3 beverages available”
|
||||
```
|
||||
|
||||
在前面的例子中,通过 `Beverage.allCases` 可以访问到包含 `Beverage` 枚举所有成员的集合。`allCases` 的使用方法和其它一般集合一样——集合中的元素是枚举类型的实例,所以在上面的情况中,这些元素是 `Beverage` 值。在前面的例子中,统计了总共有多少个枚举成员。而在下面的例子中,则使用 `for` 循环来遍历所有枚举成员。
|
||||
@ -187,7 +187,7 @@ case .upc(let numberSystem, let manufacturer, let product, let check):
|
||||
case .qrCode(let productCode):
|
||||
print("QR code: \(productCode).")
|
||||
}
|
||||
// 打印 "QR code: ABCDEFGHIJKLMNOP."
|
||||
// 打印“QR code: ABCDEFGHIJKLMNOP.”
|
||||
```
|
||||
|
||||
如果一个枚举成员的所有关联值都被提取为常量,或者都被提取为变量,为了简洁,你可以只在成员名称前标注一个 `let` 或者 `var`:
|
||||
@ -199,7 +199,7 @@ case let .upc(numberSystem, manufacturer, product, check):
|
||||
case let .qrCode(productCode):
|
||||
print("QR code: \(productCode).")
|
||||
}
|
||||
// 打印 "QR code: ABCDEFGHIJKLMNOP."
|
||||
// 打印“QR code: ABCDEFGHIJKLMNOP.”
|
||||
```
|
||||
|
||||
<a name="raw_values"></a>
|
||||
@ -296,7 +296,7 @@ if let somePlanet = Planet(rawValue: positionToFind) {
|
||||
} else {
|
||||
print("There isn't a planet at position \(positionToFind)")
|
||||
}
|
||||
// 打印 "There isn't a planet at position 11"
|
||||
// 打印“There isn't a planet at position 11”
|
||||
```
|
||||
|
||||
这个例子使用了可选绑定(optional binding),试图通过原始值 `11` 来访问一个行星。`if let somePlanet = Planet(rawValue: 11)` 语句创建了一个可选 `Planet`,如果可选 `Planet` 的值存在,就会赋值给 `somePlanet`。在这个例子中,无法检索到位置为 `11` 的行星,所以 `else` 分支被执行。
|
||||
@ -350,7 +350,7 @@ func evaluate(_ expression: ArithmeticExpression) -> Int {
|
||||
}
|
||||
|
||||
print(evaluate(product))
|
||||
// 打印 "18"
|
||||
// 打印“18”
|
||||
```
|
||||
|
||||
该函数如果遇到纯数字,就直接返回该数字的值。如果遇到的是加法或乘法运算,则分别计算左边表达式和右边表达式的值,然后相加或相乘。
|
||||
|
||||
@ -138,7 +138,7 @@ var square = Rect(origin: Point(x: 0.0, y: 0.0),
|
||||
let initialSquareCenter = square.center
|
||||
square.center = Point(x: 15.0, y: 15.0)
|
||||
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
|
||||
// 打印 "square.origin is now at (10.0, 10.0)”
|
||||
// 打印“square.origin is now at (10.0, 10.0)”
|
||||
```
|
||||
|
||||
这个例子定义了 3 个结构体来描述几何形状:
|
||||
@ -200,7 +200,7 @@ struct Cuboid {
|
||||
}
|
||||
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
|
||||
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
|
||||
// 打印 "the volume of fourByFiveByTwo is 40.0"
|
||||
// 打印“the volume of fourByFiveByTwo is 40.0”
|
||||
```
|
||||
|
||||
这个例子定义了一个名为 `Cuboid` 的结构体,表示三维空间的立方体,包含 `width`、`height` 和 `depth` 属性。结构体还有一个名为 `volume` 的只读计算属性用来返回立方体的体积。为 `volume` 提供 setter 毫无意义,因为无法确定如何修改 `width`、`height` 和 `depth` 三者的值来匹配新的 `volume`。然而,`Cuboid` 提供一个只读计算属性来让外部用户直接获取体积是很有用的。
|
||||
@ -264,7 +264,7 @@ stepCounter.totalSteps = 896
|
||||
|
||||
> 注意
|
||||
>
|
||||
> 如果将属性通过 in-out 方式传入函数,`willSet` 和 `didSet` 也会调用。这是因为 in-out 参数采用了拷入拷出模式:即在函数内部使用的是参数的 copy,函数结束后,又对参数重新赋值。关于 in-out 参数详细的介绍,请参考[输入输出参数](../chapter3/05_Declarations.html#in-out_parameters)
|
||||
> 如果将属性通过 in-out 方式传入函数,`willSet` 和 `didSet` 也会调用。这是因为 in-out 参数采用了拷入拷出模式:即在函数内部使用的是参数的 copy,函数结束后,又对参数重新赋值。关于 in-out 参数详细的介绍,请参考[输入输出参数](../chapter3/05_Declarations.html#in-out_parameters)。
|
||||
|
||||
<a name="global_and_local_variables"></a>
|
||||
## 全局变量和局部变量
|
||||
@ -340,14 +340,14 @@ class SomeClass {
|
||||
|
||||
```swift
|
||||
print(SomeStructure.storedTypeProperty)
|
||||
// 打印 "Some value."
|
||||
// 打印“Some value.”
|
||||
SomeStructure.storedTypeProperty = "Another value."
|
||||
print(SomeStructure.storedTypeProperty)
|
||||
// 打印 "Another value.”
|
||||
// 打印“Another value.”
|
||||
print(SomeEnumeration.computedTypeProperty)
|
||||
// 打印 "6"
|
||||
// 打印“6”
|
||||
print(SomeClass.computedTypeProperty)
|
||||
// 打印 "27"
|
||||
// 打印“27”
|
||||
```
|
||||
|
||||
下面的例子定义了一个结构体,使用两个存储型类型属性来表示两个声道的音量,每个声道具有 `0` 到 `10` 之间的整数音量。
|
||||
|
||||
@ -80,7 +80,7 @@ let somePoint = Point(x: 4.0, y: 5.0)
|
||||
if somePoint.isToTheRightOfX(1.0) {
|
||||
print("This point is to the right of the line where x == 1.0")
|
||||
}
|
||||
// 打印 "This point is to the right of the line where x == 1.0"
|
||||
// 打印“This point is to the right of the line where x == 1.0”
|
||||
```
|
||||
|
||||
如果不使用 `self` 前缀,Swift 就认为两次使用的 `x` 都指的是名称为 `x` 的函数参数。
|
||||
@ -105,7 +105,7 @@ struct Point {
|
||||
var somePoint = Point(x: 1.0, y: 1.0)
|
||||
somePoint.moveByX(2.0, y: 3.0)
|
||||
print("The point is now at (\(somePoint.x), \(somePoint.y))")
|
||||
// 打印 "The point is now at (3.0, 4.0)"
|
||||
// 打印“The point is now at (3.0, 4.0)”
|
||||
```
|
||||
|
||||
上面的 `Point` 结构体定义了一个可变方法 `moveByX(_:y:)` 来移动 `Point` 实例到给定的位置。该方法被调用时修改了这个点,而不是返回一个新的点。方法定义时加上了 `mutating` 关键字,从而允许修改属性。
|
||||
@ -244,7 +244,7 @@ class Player {
|
||||
var player = Player(name: "Argyrios")
|
||||
player.complete(level: 1)
|
||||
print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
|
||||
// 打印 "highest unlocked level is now 2"
|
||||
// 打印“highest unlocked level is now 2”
|
||||
```
|
||||
|
||||
如果你创建了第二个玩家,并尝试让他开始一个没有被任何玩家解锁的等级,那么试图设置玩家当前等级将会失败:
|
||||
@ -256,5 +256,5 @@ if player.tracker.advance(to: 6) {
|
||||
} else {
|
||||
print("level 6 has not yet been unlocked")
|
||||
}
|
||||
// 打印 "level 6 has not yet been unlocked"
|
||||
// 打印“level 6 has not yet been unlocked”
|
||||
```
|
||||
|
||||
@ -41,7 +41,7 @@ struct TimesTable {
|
||||
}
|
||||
let threeTimesTable = TimesTable(multiplier: 3)
|
||||
print("six times three is \(threeTimesTable[6])")
|
||||
// 打印 "six times three is 18"
|
||||
// 打印“six times three is 18”
|
||||
```
|
||||
|
||||
在上例中,创建了一个 `TimesTable` 实例,用来表示整数 `3` 的乘法表。数值 `3` 被传递给结构体的构造函数,作为实例成员 `multiplier` 的值。
|
||||
|
||||
@ -41,7 +41,7 @@ let someVehicle = Vehicle()
|
||||
|
||||
```swift
|
||||
print("Vehicle: \(someVehicle.description)")
|
||||
// 打印 "Vehicle: traveling at 0.0 miles per hour"
|
||||
// 打印“Vehicle: traveling at 0.0 miles per hour”
|
||||
```
|
||||
|
||||
`Vehicle` 类定义了一个具有通用特性的车辆类,但实际上对于它本身来说没什么用处。为了让它变得更加有用,还需要进一步完善它,从而能够描述一个具体类型的车辆。
|
||||
@ -83,7 +83,7 @@ bicycle.hasBasket = true
|
||||
```swift
|
||||
bicycle.currentSpeed = 15.0
|
||||
print("Bicycle: \(bicycle.description)")
|
||||
// 打印 "Bicycle: traveling at 15.0 miles per hour"
|
||||
// 打印“Bicycle: traveling at 15.0 miles per hour”
|
||||
```
|
||||
|
||||
子类还可以继续被其它类继承,下面的示例为 `Bicycle` 创建了一个名为 `Tandem`(双人自行车)的子类:
|
||||
@ -104,7 +104,7 @@ tandem.hasBasket = true
|
||||
tandem.currentNumberOfPassengers = 2
|
||||
tandem.currentSpeed = 22.0
|
||||
print("Tandem: \(tandem.description)")
|
||||
// 打印:"Tandem: traveling at 22.0 miles per hour"
|
||||
// 打印:“Tandem: traveling at 22.0 miles per hour”
|
||||
```
|
||||
|
||||
<a name="overriding"></a>
|
||||
@ -145,7 +145,7 @@ class Train: Vehicle {
|
||||
```swift
|
||||
let train = Train()
|
||||
train.makeNoise()
|
||||
// 打印 "Choo Choo"
|
||||
// 打印“Choo Choo”
|
||||
```
|
||||
|
||||
### 重写属性
|
||||
@ -182,7 +182,7 @@ let car = Car()
|
||||
car.currentSpeed = 25.0
|
||||
car.gear = 3
|
||||
print("Car: \(car.description)")
|
||||
// 打印 "Car: traveling at 25.0 miles per hour in gear 3"
|
||||
// 打印“Car: traveling at 25.0 miles per hour in gear 3”
|
||||
```
|
||||
|
||||
<a name="overriding_property_observers"></a>
|
||||
@ -213,7 +213,7 @@ class AutomaticCar: Car {
|
||||
let automatic = AutomaticCar()
|
||||
automatic.currentSpeed = 35.0
|
||||
print("AutomaticCar: \(automatic.description)")
|
||||
// 打印 "AutomaticCar: traveling at 35.0 miles per hour in gear 4"
|
||||
// 打印“AutomaticCar: traveling at 35.0 miles per hour in gear 4”
|
||||
```
|
||||
|
||||
<a name="preventing_overrides"></a>
|
||||
|
||||
@ -40,7 +40,7 @@ struct Fahrenheit {
|
||||
}
|
||||
var f = Fahrenheit()
|
||||
print("The default temperature is \(f.temperature)° Fahrenheit")
|
||||
// 打印 "The default temperature is 32.0° Fahrenheit"
|
||||
// 打印“The default temperature is 32.0° Fahrenheit”
|
||||
```
|
||||
|
||||
这个结构体定义了一个不带形参的构造器 `init`,并在里面将存储型属性 `temperature` 的值初始化为 `32.0`(华氏温度下水的冰点)。
|
||||
@ -184,7 +184,7 @@ class SurveyQuestion {
|
||||
|
||||
let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
|
||||
cheeseQuestion.ask()
|
||||
// 打印 "Do you like cheese?"
|
||||
// 打印“Do you like cheese?”
|
||||
cheeseQuestion.response = "Yes, I do like cheese."
|
||||
```
|
||||
|
||||
@ -214,7 +214,7 @@ class SurveyQuestion {
|
||||
}
|
||||
let beetsQuestion = SurveyQuestion(text: "How about beets?")
|
||||
beetsQuestion.ask()
|
||||
// 打印 "How about beets?"
|
||||
// 打印“How about beets?”
|
||||
beetsQuestion.response = "I also like beets. (But not with cheese.)"
|
||||
```
|
||||
|
||||
@ -540,7 +540,7 @@ class Bicycle: Vehicle {
|
||||
```swift
|
||||
let bicycle = Bicycle()
|
||||
print("Bicycle: \(bicycle.description)")
|
||||
// 打印 "Bicycle: 2 wheel(s)"
|
||||
// 打印“Bicycle: 2 wheel(s)”
|
||||
```
|
||||
|
||||
如果父类的构造器没有在阶段 2 过程中做自定义操作,并且父类有一个无参数的自定义构造器。你可以在所有父类的存储属性赋值之后省略 `super.init()` 的调用。
|
||||
@ -742,7 +742,7 @@ let pi = 3.14159
|
||||
if let valueMaintained = Int(exactly: wholeNumber) {
|
||||
print("\(wholeNumber) conversion to Int maintains value of \(valueMaintained)")
|
||||
}
|
||||
// 打印 "12345.0 conversion to Int maintains value of 12345"
|
||||
// 打印“12345.0 conversion to Int maintains value of 12345”
|
||||
|
||||
let valueChanged = Int(exactly: pi)
|
||||
// valueChanged 是 Int? 类型,不是 Int 类型
|
||||
@ -750,7 +750,7 @@ let valueChanged = Int(exactly: pi)
|
||||
if valueChanged == nil {
|
||||
print("\(pi) conversion to Int does not maintain value")
|
||||
}
|
||||
// 打印 "3.14159 conversion to Int does not maintain value"
|
||||
// 打印“3.14159 conversion to Int does not maintain value”
|
||||
```
|
||||
|
||||
下例中,定义了一个名为 `Animal` 的结构体,其中有一个名为 `species` 的 `String` 类型的常量属性。同时该结构体还定义了一个接受一个名为 `species` 的 `String` 类型形参的可失败构造器。这个可失败构造器检查传入的`species` 值是否为一个空字符串。如果为空字符串,则构造失败。否则,`species` 属性被赋值,构造成功。
|
||||
@ -776,7 +776,7 @@ let someCreature = Animal(species: "Giraffe")
|
||||
if let giraffe = someCreature {
|
||||
print("An animal was initialized with a species of \(giraffe.species)")
|
||||
}
|
||||
// 打印 "An animal was initialized with a species of Giraffe"
|
||||
// 打印“An animal was initialized with a species of Giraffe”
|
||||
```
|
||||
|
||||
如果你给该可失败构造器传入一个空字符串到形参 `species`,则会导致构造失败:
|
||||
@ -788,7 +788,7 @@ let anonymousCreature = Animal(species: "")
|
||||
if anonymousCreature == nil {
|
||||
print("The anonymous creature could not be initialized")
|
||||
}
|
||||
// 打印 "The anonymous creature could not be initialized"
|
||||
// 打印“The anonymous creature could not be initialized”
|
||||
```
|
||||
|
||||
> 注意
|
||||
@ -827,13 +827,13 @@ let fahrenheitUnit = TemperatureUnit(symbol: "F")
|
||||
if fahrenheitUnit != nil {
|
||||
print("This is a defined temperature unit, so initialization succeeded.")
|
||||
}
|
||||
// 打印 "This is a defined temperature unit, so initialization succeeded."
|
||||
// 打印“This is a defined temperature unit, so initialization succeeded.”
|
||||
|
||||
let unknownUnit = TemperatureUnit(symbol: "X")
|
||||
if unknownUnit == nil {
|
||||
print("This is not a defined temperature unit, so initialization failed.")
|
||||
}
|
||||
// 打印 "This is not a defined temperature unit, so initialization failed."
|
||||
// 打印“This is not a defined temperature unit, so initialization failed.”
|
||||
```
|
||||
|
||||
<a name="failable_initializers_for_enumerations_with_raw_values"></a>
|
||||
@ -852,13 +852,13 @@ let fahrenheitUnit = TemperatureUnit(rawValue: "F")
|
||||
if fahrenheitUnit != nil {
|
||||
print("This is a defined temperature unit, so initialization succeeded.")
|
||||
}
|
||||
// 打印 "This is a defined temperature unit, so initialization succeeded."
|
||||
// 打印“This is a defined temperature unit, so initialization succeeded.”
|
||||
|
||||
let unknownUnit = TemperatureUnit(rawValue: "X")
|
||||
if unknownUnit == nil {
|
||||
print("This is not a defined temperature unit, so initialization failed.")
|
||||
}
|
||||
// 打印 "This is not a defined temperature unit, so initialization failed."
|
||||
// 打印“This is not a defined temperature unit, so initialization failed.”
|
||||
```
|
||||
|
||||
<a name="propagation_of_initialization_failure"></a>
|
||||
@ -901,7 +901,7 @@ class CartItem: Product {
|
||||
if let twoSocks = CartItem(name: "sock", quantity: 2) {
|
||||
print("Item: \(twoSocks.name), quantity: \(twoSocks.quantity)")
|
||||
}
|
||||
// 打印 "Item: sock, quantity: 2"
|
||||
// 打印“Item: sock, quantity: 2”
|
||||
```
|
||||
|
||||
倘若你以一个值为 0 的 `quantity` 来创建一个 `CartItem` 实例,那么将导致 `CartItem` 构造器失败:
|
||||
@ -912,7 +912,7 @@ if let zeroShirts = CartItem(name: "shirt", quantity: 0) {
|
||||
} else {
|
||||
print("Unable to initialize zero shirts")
|
||||
}
|
||||
// 打印 "Unable to initialize zero shirts"
|
||||
// 打印“Unable to initialize zero shirts”
|
||||
```
|
||||
|
||||
同样地,如果你尝试传入一个值为空字符串的 `name` 来创建一个 `CartItem` 实例,那么将导致父类 `Product` 的构造过程失败:
|
||||
@ -923,7 +923,7 @@ if let oneUnnamed = CartItem(name: "", quantity: 1) {
|
||||
} else {
|
||||
print("Unable to initialize one unnamed product")
|
||||
}
|
||||
// 打印 "Unable to initialize one unnamed product"
|
||||
// 打印“Unable to initialize one unnamed product”
|
||||
```
|
||||
|
||||
<a name="overriding_a_failable_initializer"></a>
|
||||
@ -1077,7 +1077,7 @@ struct Chessboard {
|
||||
```swift
|
||||
let board = Chessboard()
|
||||
print(board.squareIsBlackAt(row: 0, column: 1))
|
||||
// 打印 "true"
|
||||
// 打印“true”
|
||||
print(board.squareIsBlackAt(row: 7, column: 7))
|
||||
// 打印 "false”
|
||||
// 打印“false”
|
||||
```
|
||||
|
||||
@ -68,9 +68,9 @@ class Player {
|
||||
```swift
|
||||
var playerOne: Player? = Player(coins: 100)
|
||||
print("A new player has joined the game with \(playerOne!.coinsInPurse) coins")
|
||||
// 打印 "A new player has joined the game with 100 coins"
|
||||
// 打印“A new player has joined the game with 100 coins”
|
||||
print("There are now \(Bank.coinsInBank) coins left in the bank")
|
||||
// 打印 "There are now 9900 coins left in the bank"
|
||||
// 打印“There are now 9900 coins left in the bank”
|
||||
```
|
||||
|
||||
创建一个 `Player` 实例的时候,会向 `Bank` 对象申请得到 100 个硬币,前提是有足够的硬币可用。这个 `Player` 实例存储在一个名为 `playerOne` 的可选类型的变量中。这里使用了一个可选类型的变量,是因为玩家可以随时离开游戏,设置为可选使你可以追踪玩家当前是否在游戏中。
|
||||
@ -80,9 +80,9 @@ print("There are now \(Bank.coinsInBank) coins left in the bank")
|
||||
```swift
|
||||
playerOne!.win(coins: 2_000)
|
||||
print("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins")
|
||||
// 打印 "PlayerOne won 2000 coins & now has 2100 coins"
|
||||
// 打印“PlayerOne won 2000 coins & now has 2100 coins”
|
||||
print("The bank now only has \(Bank.coinsInBank) coins left")
|
||||
// 打印 "The bank now only has 7900 coins left"
|
||||
// 打印“The bank now only has 7900 coins left”
|
||||
```
|
||||
|
||||
在这里,玩家已经赢得了 2,000 枚硬币,所以玩家的钱包中现在有 2,100 枚硬币,而 `Bank` 对象只剩余 7,900 枚硬币。
|
||||
@ -90,9 +90,9 @@ print("The bank now only has \(Bank.coinsInBank) coins left")
|
||||
```swift
|
||||
playerOne = nil
|
||||
print("PlayerOne has left the game")
|
||||
// 打印 "PlayerOne has left the game"
|
||||
// 打印“PlayerOne has left the game”
|
||||
print("The bank now has \(Bank.coinsInBank) coins")
|
||||
// 打印 "The bank now has 10000 coins"
|
||||
// 打印“The bank now has 10000 coins”
|
||||
```
|
||||
|
||||
玩家现在已经离开了游戏。这通过将可选类型的 `playerOne` 变量设置为 `nil` 来表示,意味着“没有 `Player` 实例”。当这一切发生时,`playerOne` 变量对 `Player` 实例的引用被破坏了。没有其它属性或者变量引用 `Player` 实例,因此该实例会被释放,以便回收内存。在这之前,该实例的析构器被自动调用,玩家的硬币被返还给银行。
|
||||
|
||||
@ -54,7 +54,7 @@ if let roomCount = john.residence?.numberOfRooms {
|
||||
} else {
|
||||
print("Unable to retrieve the number of rooms.")
|
||||
}
|
||||
// 打印 “Unable to retrieve the number of rooms.”
|
||||
// 打印“Unable to retrieve the number of rooms.”
|
||||
```
|
||||
|
||||
在 `residence` 后面添加问号之后,Swift 就会在 `residence` 不为 `nil` 的情况下访问 `numberOfRooms`。
|
||||
@ -77,7 +77,7 @@ if let roomCount = john.residence?.numberOfRooms {
|
||||
} else {
|
||||
print("Unable to retrieve the number of rooms.")
|
||||
}
|
||||
// 打印 “John's residence has 1 room(s).”
|
||||
// 打印“John's residence has 1 room(s).”
|
||||
```
|
||||
|
||||
<a name="defining_model_classes_for_optional_chaining"></a>
|
||||
@ -170,7 +170,7 @@ if let roomCount = john.residence?.numberOfRooms {
|
||||
} else {
|
||||
print("Unable to retrieve the number of rooms.")
|
||||
}
|
||||
// 打印 “Unable to retrieve the number of rooms.”
|
||||
// 打印“Unable to retrieve the number of rooms.”
|
||||
```
|
||||
|
||||
因为 `john.residence` 为 `nil`,所以这个可选链式调用依旧会像先前一样失败。
|
||||
@ -186,7 +186,7 @@ john.residence?.address = someAddress
|
||||
|
||||
在这个例子中,通过 `john.residence` 来设定 `address` 属性也会失败,因为 `john.residence` 当前为 `nil`。
|
||||
|
||||
上面代码中的赋值过程是可选链式调用的一部分,这意味着可选链式调用失败时,等号右侧的代码不会被执行。对于上面的代码来说,很难验证这一点,因为像这样赋值一个常量没有任何副作用。下面的代码完成了同样的事情,但是它使用一个函数来创建 `Address` 实例,然后将该实例返回用于赋值。该函数会在返回前打印 “Function was called”,这使你能验证等号右侧的代码是否被执行。
|
||||
上面代码中的赋值过程是可选链式调用的一部分,这意味着可选链式调用失败时,等号右侧的代码不会被执行。对于上面的代码来说,很难验证这一点,因为像这样赋值一个常量没有任何副作用。下面的代码完成了同样的事情,但是它使用一个函数来创建 `Address` 实例,然后将该实例返回用于赋值。该函数会在返回前打印“Function was called”,这使你能验证等号右侧的代码是否被执行。
|
||||
|
||||
```swift
|
||||
func createAddress() -> Address {
|
||||
@ -226,7 +226,7 @@ if john.residence?.printNumberOfRooms() != nil {
|
||||
} else {
|
||||
print("It was not possible to print the number of rooms.")
|
||||
}
|
||||
// 打印 “It was not possible to print the number of rooms.”
|
||||
// 打印“It was not possible to print the number of rooms.”
|
||||
```
|
||||
|
||||
同样的,可以据此判断通过可选链式调用为属性赋值是否成功。在上面的[通过可选链式调用访问属性](#accessing_properties_through_optional_chaining)的例子中,我们尝试给 `john.residence` 中的 `address` 属性赋值,即使 `residence` 为 `nil`。通过可选链式调用给属性赋值会返回 `Void?`,通过判断返回值是否为 `nil` 就可以知道赋值是否成功:
|
||||
@ -237,7 +237,7 @@ if (john.residence?.address = someAddress) != nil {
|
||||
} else {
|
||||
print("It was not possible to set the address.")
|
||||
}
|
||||
// 打印 “It was not possible to set the address.”
|
||||
// 打印“It was not possible to set the address.”
|
||||
```
|
||||
|
||||
<a name="accessing_subscripts_through_optional_chaining"></a>
|
||||
@ -257,7 +257,7 @@ if let firstRoomName = john.residence?[0].name {
|
||||
} else {
|
||||
print("Unable to retrieve the first room name.")
|
||||
}
|
||||
// 打印 “Unable to retrieve the first room name.”
|
||||
// 打印“Unable to retrieve the first room name.”
|
||||
```
|
||||
|
||||
在这个例子中,问号直接放在 `john.residence` 的后面,并且在方括号的前面,因为 `john.residence` 是可选值。
|
||||
@ -283,7 +283,7 @@ if let firstRoomName = john.residence?[0].name {
|
||||
} else {
|
||||
print("Unable to retrieve the first room name.")
|
||||
}
|
||||
// 打印 “The first room name is Living Room.”
|
||||
// 打印“The first room name is Living Room.”
|
||||
```
|
||||
|
||||
<a name="accessing_subscripts_of_optional_type"></a>
|
||||
@ -324,7 +324,7 @@ if let johnsStreet = john.residence?.address?.street {
|
||||
} else {
|
||||
print("Unable to retrieve the address.")
|
||||
}
|
||||
// 打印 “Unable to retrieve the address.”
|
||||
// 打印“Unable to retrieve the address.”
|
||||
```
|
||||
|
||||
`john.residence` 现在包含一个有效的 `Residence` 实例。然而,`john.residence.address` 的值当前为 `nil`。因此,调用 `john.residence?.address?.street` 会失败。
|
||||
@ -344,7 +344,7 @@ if let johnsStreet = john.residence?.address?.street {
|
||||
} else {
|
||||
print("Unable to retrieve the address.")
|
||||
}
|
||||
// 打印 “John's street name is Laurel Street.”
|
||||
// 打印“John's street name is Laurel Street.”
|
||||
```
|
||||
|
||||
在上面的例子中,因为 `john.residence` 包含一个有效的 `Address` 实例,所以对 `john.residence` 的 `address` 属性赋值将会成功。
|
||||
@ -360,14 +360,13 @@ if let johnsStreet = john.residence?.address?.street {
|
||||
if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {
|
||||
print("John's building identifier is \(buildingIdentifier).")
|
||||
}
|
||||
// 打印 “John's building identifier is The Larches.”
|
||||
// 打印“John's building identifier is The Larches.”
|
||||
```
|
||||
|
||||
如果要在该方法的返回值上进行可选链式调用,在方法的圆括号后面加上问号即可:
|
||||
|
||||
```swift
|
||||
if let beginsWithThe =
|
||||
|
||||
john.residence?.address?.buildingIdentifier()?.hasPrefix("The") {
|
||||
if beginsWithThe {
|
||||
print("John's building identifier begins with \"The\".")
|
||||
@ -375,7 +374,7 @@ if let beginsWithThe =
|
||||
print("John's building identifier does not begin with \"The\".")
|
||||
}
|
||||
}
|
||||
// 打印 “John's building identifier begins with "The".”
|
||||
// 打印“John's building identifier begins with "The".”
|
||||
```
|
||||
|
||||
> 注意
|
||||
|
||||
@ -169,7 +169,7 @@ do {
|
||||
} catch {
|
||||
print("Unexpected error: \(error).")
|
||||
}
|
||||
// 打印 “Insufficient funds. Please insert an additional 2 coins.”
|
||||
// 打印“Insufficient funds. Please insert an additional 2 coins.”
|
||||
```
|
||||
|
||||
上面的例子中,`buyFavoriteSnack(person:vendingMachine:)` 函数在一个 `try` 表达式中被调用,是因为它能抛出错误。如果错误被抛出,相应的执行会马上转移到 `catch` 子句中,并判断这个错误是否要被继续传递下去。如果错误没有被匹配,它会被最后一个 `catch` 语句捕获,并赋值给一个 `error` 常量。如果没有错误被抛出,`do` 子句中余下的语句就会被执行。
|
||||
@ -192,7 +192,7 @@ do {
|
||||
} catch {
|
||||
print("Unexpected non-vending-machine-related error: \(error)")
|
||||
}
|
||||
// 打印 "Invalid selection, out of stock, or not enough money."
|
||||
// 打印“Invalid selection, out of stock, or not enough money.”
|
||||
```
|
||||
|
||||
如果 `vend(itemNamed:)` 抛出的是一个 `VendingMachineError` 类型的错误,`nourish(with:)` 会打印一条消息,否则 `nourish(with:)` 会将错误抛给它的调用方。这个错误之后会被通用的 `catch` 语句捕获。
|
||||
|
||||
@ -77,7 +77,7 @@ for item in library {
|
||||
}
|
||||
|
||||
print("Media library contains \(movieCount) movies and \(songCount) songs")
|
||||
// 打印 "Media library contains 2 movies and 3 songs"
|
||||
// 打印“Media library contains 2 movies and 3 songs”
|
||||
```
|
||||
|
||||
示例迭代了数组 `library` 中的所有项。每一次,`for-in` 循环设置
|
||||
|
||||
@ -69,7 +69,7 @@ struct BlackjackCard {
|
||||
```swift
|
||||
let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
|
||||
print("theAceOfSpades: \(theAceOfSpades.description)")
|
||||
// 打印 “theAceOfSpades: suit is ♠, value is 1 or 11”
|
||||
// 打印“theAceOfSpades: suit is ♠, value is 1 or 11”
|
||||
```
|
||||
|
||||
尽管 `Rank` 和 `Suit` 嵌套在 `BlackjackCard` 中,但它们的类型仍可从上下文中推断出来,所以在初始化实例时能够单独通过成员名称(`.ace` 和 `.spades`)引用枚举实例。在上面的例子中,`description` 属性正确地反映了黑桃 A 牌具有 `1` 和 `11` 两个值。
|
||||
|
||||
@ -254,7 +254,7 @@ func printIntegerKinds(_ numbers: [Int]) {
|
||||
print("")
|
||||
}
|
||||
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
|
||||
// 打印 "+ + - 0 - 0 + "
|
||||
// 打印“+ + - 0 - 0 + ”
|
||||
```
|
||||
|
||||
方法 **printIntegerKinds(_:)**,使用一个 **Int** 类型的数组作为输入,然后依次迭代这些值。对于数组中的每一个整数,方法会检查它的 **kind** 计算型属性,然后打印适当的描述。
|
||||
|
||||
@ -139,9 +139,9 @@ class LinearCongruentialGenerator: RandomNumberGenerator {
|
||||
}
|
||||
let generator = LinearCongruentialGenerator()
|
||||
print("Here's a random number: \(generator.random())")
|
||||
// 打印 “Here's a random number: 0.37464991998171”
|
||||
// 打印“Here's a random number: 0.37464991998171”
|
||||
print("And another one: \(generator.random())")
|
||||
// 打印 “And another one: 0.729023776863283”
|
||||
// 打印“And another one: 0.729023776863283”
|
||||
```
|
||||
|
||||
<a name="mutating_method_requirements"></a>
|
||||
@ -444,7 +444,7 @@ extension Dice: TextRepresentable {
|
||||
```swift
|
||||
let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
|
||||
print(d12.textualDescription)
|
||||
// 打印 “A 12-sided dice”
|
||||
// 打印“A 12-sided dice”
|
||||
```
|
||||
|
||||
同样,`SnakesAndLadders` 类也可以通过扩展遵循 `TextRepresentable` 协议:
|
||||
@ -456,7 +456,7 @@ extension SnakesAndLadders: TextRepresentable {
|
||||
}
|
||||
}
|
||||
print(game.textualDescription)
|
||||
// 打印 “A game of Snakes and Ladders with 25 squares”
|
||||
// 打印“A game of Snakes and Ladders with 25 squares”
|
||||
```
|
||||
|
||||
<a name="Conditionally_Conforming_to_a_Protocol"></a>
|
||||
@ -475,7 +475,7 @@ extension Array: TextRepresentable where Element: TextRepresentable {
|
||||
}
|
||||
let myDice = [d6, d12]
|
||||
print(myDice.textualDescription)
|
||||
// 打印 "[A 6-sided dice, A 12-sided dice]"
|
||||
// 打印“[A 6-sided dice, A 12-sided dice]”
|
||||
```
|
||||
|
||||
<a name="declaring_protocol_adoption_with_an_extension"></a>
|
||||
@ -499,7 +499,7 @@ extension Hamster: TextRepresentable {}
|
||||
let simonTheHamster = Hamster(name: "Simon")
|
||||
let somethingTextRepresentable: TextRepresentable = simonTheHamster
|
||||
print(somethingTextRepresentable.textualDescription)
|
||||
// 打印 “A hamster named Simon”
|
||||
// 打印“A hamster named Simon”
|
||||
```
|
||||
|
||||
> 注意
|
||||
@ -626,7 +626,7 @@ func wishHappyBirthday(to celebrator: Named & Aged) {
|
||||
}
|
||||
let birthdayPerson = Person(name: "Malcolm", age: 21)
|
||||
wishHappyBirthday(to: birthdayPerson)
|
||||
// 打印 “Happy birthday Malcolm - you're 21!”
|
||||
// 打印“Happy birthday Malcolm - you're 21!”
|
||||
```
|
||||
|
||||
`Named` 协议包含 `String` 类型的 `name` 属性。`Aged` 协议包含 `Int` 类型的 `age` 属性。`Person` 结构体遵循了这两个协议。
|
||||
@ -871,9 +871,9 @@ extension RandomNumberGenerator {
|
||||
```swift
|
||||
let generator = LinearCongruentialGenerator()
|
||||
print("Here's a random number: \(generator.random())")
|
||||
// 打印 “Here's a random number: 0.37464991998171”
|
||||
// 打印“Here's a random number: 0.37464991998171”
|
||||
print("And here's a random Boolean: \(generator.randomBool())")
|
||||
// 打印 “And here's a random Boolean: true”
|
||||
// 打印“And here's a random Boolean: true”
|
||||
```
|
||||
|
||||
<a name="providing_default_implementations"></a>
|
||||
@ -930,9 +930,9 @@ let differentNumbers = [100, 100, 200, 100, 200]
|
||||
|
||||
```swift
|
||||
print(equalNumbers.allEqual())
|
||||
// 打印 "true"
|
||||
// 打印“true”
|
||||
print(differentNumbers.allEqual())
|
||||
// 打印 "false"
|
||||
// 打印“false”
|
||||
```
|
||||
|
||||
> 注意
|
||||
|
||||
@ -65,7 +65,7 @@ var someInt = 3
|
||||
var anotherInt = 107
|
||||
swapTwoInts(&someInt, &anotherInt)
|
||||
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
|
||||
// 打印 "someInt is now 107, and anotherInt is now 3"
|
||||
// 打印“someInt is now 107, and anotherInt is now 3”
|
||||
|
||||
```
|
||||
`swapTwoInts(_:_:)` 函数很实用,但它只能作用于 `Int` 类型。如果你想交换两个 `String` 类型值,或者 `Double` 类型值,你必须编写对应的函数,类似下面 `swapTwoStrings(_:_:)` 和 `swapTwoDoubles(_:_:)` 函数:
|
||||
@ -268,7 +268,7 @@ extension Stack {
|
||||
if let topItem = stackOfStrings.topItem {
|
||||
print("The top item on the stack is \(topItem).")
|
||||
}
|
||||
// 打印 “The top item on the stack is tres.”
|
||||
// 打印“The top item on the stack is tres.”
|
||||
```
|
||||
|
||||
<a name="type_constraints"></a>
|
||||
@ -316,7 +316,7 @@ let strings = ["cat", "dog", "llama", "parakeet", "terrapin"]
|
||||
if let foundIndex = findIndex(ofString: "llama", in: strings) {
|
||||
print("The index of llama is \(foundIndex)")
|
||||
}
|
||||
// 打印 “The index of llama is 2”
|
||||
// 打印“The index of llama is 2”
|
||||
```
|
||||
如果只能查找字符串在数组中的索引,用处不是很大。不过,你可以用占位类型 `T` 替换 `String` 类型来写出具有相同功能的泛型函数 `findIndex(_:_:)`。
|
||||
|
||||
@ -598,7 +598,7 @@ if allItemsMatch(stackOfStrings, arrayOfStrings) {
|
||||
} else {
|
||||
print("Not all items match.")
|
||||
}
|
||||
// 打印 “All items match.”
|
||||
// 打印“All items match.”
|
||||
```
|
||||
上面的例子创建 `Stack` 实例来存储 `String` 值,然后将三个字符串压栈。这个例子还通过数组字面量创建了一个 `Array` 实例,数组中包含同栈中一样的三个字符串。即使栈和数组是不同的类型,但它们都遵从 `Container` 协议,而且它们都包含相同类型的值。因此你可以用这两个容器作为参数来调用 `allItemsMatch(_:_:)` 函数。在上面的例子中,`allItemsMatch(_:_:)` 函数正确地显示了这两个容器中的所有元素都是相互匹配的。
|
||||
|
||||
@ -630,7 +630,7 @@ if stackOfStrings.isTop("tres") {
|
||||
} else {
|
||||
print("Top element is something else.")
|
||||
}
|
||||
// 打印 "Top element is tres."
|
||||
// 打印“Top element is tres.”
|
||||
```
|
||||
|
||||
如果尝试在其元素不符合 `Equatable` 协议的栈上调用 `isTop(_:)` 方法,则会收到编译时错误。
|
||||
@ -660,7 +660,7 @@ if [9, 9, 9].startsWith(42) {
|
||||
} else {
|
||||
print("Starts with something else.")
|
||||
}
|
||||
// 打印 "Starts with something else."
|
||||
// 打印“Starts with something else.”
|
||||
```
|
||||
|
||||
上述示例中的泛型 `where` 子句要求 `Item` 遵循协议,但也可以编写一个泛型 `where` 子句去要求 `Item` 为特定类型。例如:
|
||||
@ -676,7 +676,7 @@ extension Container where Item == Double {
|
||||
}
|
||||
}
|
||||
print([1260.0, 1200.0, 98.6, 37.0].average())
|
||||
// 打印 "648.9"
|
||||
// 打印“648.9”
|
||||
```
|
||||
此示例将一个 `average()` 方法添加到 `Item` 类型为 `Double` 的容器中。此方法遍历容器中的元素将其累加,并除以容器的数量计算平均值。它将数量从 `Int` 转换为 `Double` 确保能够进行浮点除法。
|
||||
|
||||
|
||||
@ -54,7 +54,7 @@ var reference3: Person?
|
||||
|
||||
```swift
|
||||
reference1 = Person(name: "John Appleseed")
|
||||
// 打印 "John Appleseed is being initialized"
|
||||
// 打印“John Appleseed is being initialized”
|
||||
```
|
||||
|
||||
应当注意到当你调用 `Person` 类的构造器的时候,`"John Appleseed is being initialized"` 会被打印出来。由此可以确定构造器被执行。
|
||||
@ -81,7 +81,7 @@ reference2 = nil
|
||||
|
||||
```swift
|
||||
reference3 = nil
|
||||
// 打印 "John Appleseed is being deinitialized"
|
||||
// 打印“John Appleseed is being deinitialized”
|
||||
```
|
||||
|
||||
<a name="strong_reference_cycles_between_class_instances"></a>
|
||||
@ -223,7 +223,7 @@ unit4A!.tenant = john
|
||||
|
||||
```swift
|
||||
john = nil
|
||||
// 打印 "John Appleseed is being deinitialized"
|
||||
// 打印“John Appleseed is being deinitialized”
|
||||
```
|
||||
|
||||
由于再也没有指向 `Person` 实例的强引用,该实例会被销毁,且 `tenant` 属性会被赋值为 `nil`:
|
||||
@ -234,7 +234,7 @@ john = nil
|
||||
|
||||
```swift
|
||||
unit4A = nil
|
||||
// 打印 "Apartment 4A is being deinitialized"
|
||||
// 打印“Apartment 4A is being deinitialized”
|
||||
```
|
||||
|
||||
由于再也没有指向 `Person` 实例的强引用,该实例会被销毁:
|
||||
@ -318,8 +318,8 @@ john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
|
||||
|
||||
```swift
|
||||
john = nil
|
||||
// 打印 "John Appleseed is being deinitialized"
|
||||
// 打印 "Card #1234567890123456 is being deinitialized"
|
||||
// 打印“John Appleseed is being deinitialized”
|
||||
// 打印“Card #1234567890123456 is being deinitialized”
|
||||
```
|
||||
|
||||
最后的代码展示了在 `john` 变量被设为 `nil` 后 `Customer` 实例和 `CreditCard` 实例的析构器都打印出了“销毁”的信息。
|
||||
@ -376,7 +376,7 @@ class City {
|
||||
```swift
|
||||
var country = Country(name: "Canada", capitalName: "Ottawa")
|
||||
print("\(country.name)'s capital city is called \(country.capitalCity.name)")
|
||||
// 打印 "Canada's capital city is called Ottawa"
|
||||
// 打印“Canada's capital city is called Ottawa”
|
||||
```
|
||||
|
||||
在上面的例子中,使用隐式解包可选值值意味着满足了类的构造器的两个构造阶段的要求。`capitalCity` 属性在初始化完成后,能像非可选值一样使用和存取,同时还避免了循环强引用。
|
||||
@ -437,7 +437,7 @@ heading.asHTML = {
|
||||
return "<\(heading.name)>\(heading.text ?? defaultText)</\(heading.name)>"
|
||||
}
|
||||
print(heading.asHTML())
|
||||
// 打印 "<h1>some default text</h1>"
|
||||
// 打印“<h1>some default text</h1>”
|
||||
```
|
||||
|
||||
> 注意
|
||||
@ -451,7 +451,7 @@ print(heading.asHTML())
|
||||
```swift
|
||||
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
|
||||
print(paragraph!.asHTML())
|
||||
// 打印 "<p>hello, world</p>"
|
||||
// 打印“<p>hello, world</p>”
|
||||
```
|
||||
|
||||
> 注意
|
||||
@ -555,7 +555,7 @@ class HTMLElement {
|
||||
```swift
|
||||
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
|
||||
print(paragraph!.asHTML())
|
||||
// 打印 "<p>hello, world</p>"
|
||||
// 打印“<p>hello, world</p>”
|
||||
```
|
||||
|
||||
使用捕获列表后引用关系如下图所示:
|
||||
@ -566,7 +566,7 @@ print(paragraph!.asHTML())
|
||||
|
||||
```swift
|
||||
paragraph = nil
|
||||
// 打印 "p is being deinitialized"
|
||||
// 打印“p is being deinitialized”
|
||||
```
|
||||
|
||||
你可以查看[捕获列表](../chapter3/04_Expressions.html)章节,获取更多关于捕获列表的信息。
|
||||
|
||||
@ -55,7 +55,7 @@ func oneMore(than number: Int) -> Int {
|
||||
var myNumber = 1
|
||||
myNumber = oneMore(than: myNumber)
|
||||
print(myNumber)
|
||||
// 打印 "2"
|
||||
// 打印“2”
|
||||
```
|
||||
|
||||
然而,有几种被称为长期访问的内存访问方式,会在别的代码执行时持续进行。瞬时访问和长期访问的区别在于别的代码有没有可能在访问期间同时访问,也就是在时间线上的重叠。一个长期访问可以被别的长期访问或瞬时访问重叠。
|
||||
|
||||
@ -279,7 +279,7 @@ stringToEdit.value = "This string will be tracked."
|
||||
stringToEdit.value += " This edit will increment numberOfEdits."
|
||||
stringToEdit.value += " So will this one."
|
||||
print("The number of edits is \(stringToEdit.numberOfEdits)")
|
||||
// 打印 “The number of edits is 3”
|
||||
// 打印“The number of edits is 3”
|
||||
```
|
||||
|
||||
虽然你可以在其他的源文件中实例化该结构体并且获取到 `numberOfEdits` 属性的值,但是你不能对其进行赋值。这一限制保护了该记录功能的实现细节,同时还提供了方便的访问方式。
|
||||
|
||||
@ -401,7 +401,7 @@ let anotherTwoThree = Vector2D(x: 2.0, y: 3.0)
|
||||
if twoThree == anotherTwoThree {
|
||||
print("These two vectors are equivalent.")
|
||||
}
|
||||
// 打印 “These two vectors are equivalent.”
|
||||
// 打印“These two vectors are equivalent.”
|
||||
```
|
||||
|
||||
Swift 为以下数种自定义类型提供等价运算符的默认实现:
|
||||
|
||||
@ -388,7 +388,7 @@ let someInstance: SomeBaseClass = SomeSubClass()
|
||||
// someInstance 在编译期是 SomeBaseClass 类型,
|
||||
// 但是在运行期则是 SomeSubClass 类型
|
||||
type(of: someInstance).printClassName()
|
||||
// 打印 “SomeSubClass”
|
||||
// 打印“SomeSubClass”
|
||||
```
|
||||
|
||||
更多信息可以查看 Swift 标准库里的 `type(of:)`。
|
||||
|
||||
@ -196,14 +196,14 @@ func f(any: Any) { print("Function for Any") }
|
||||
func f(int: Int) { print("Function for Int") }
|
||||
let x = 10
|
||||
f(x)
|
||||
// 打印 “Function for Int”
|
||||
// 打印“Function for Int”
|
||||
|
||||
let y: Any = x
|
||||
f(y)
|
||||
// 打印 “Function for Any”
|
||||
// 打印“Function for Any”
|
||||
|
||||
f(x as Any)
|
||||
// 打印 “Function for Any”
|
||||
// 打印“Function for Any”
|
||||
```
|
||||
|
||||
桥接可将 Swift 标准库中的类型(例如 `String`)作为一个与之相关的 Foundation 类型(例如 `NSString`)来使用,而不需要新建一个实例。关于桥接的更多信息,请参阅 [*Using Swift with Cocoa and Objective-C (Swift4.1)*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216) 中的 [Working with Cocoa Data Types](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6)。
|
||||
@ -265,7 +265,7 @@ func logFunctionName(string: String = #function) {
|
||||
func myFunction() {
|
||||
logFunctionName()
|
||||
}
|
||||
myFunction() // 打印 “myFunction()”
|
||||
myFunction() // 打印“myFunction()”
|
||||
```
|
||||
|
||||
数组字面量是值的有序集合,形式如下:
|
||||
@ -441,7 +441,7 @@ let closure = { [a] in
|
||||
a = 10
|
||||
b = 10
|
||||
closure()
|
||||
// 打印 “0 10”
|
||||
// 打印“0 10”
|
||||
```
|
||||
|
||||
在示例中,变量 `b` 只有一个,然而,变量 `a` 有两个,一个在闭包外,一个在闭包内。闭包内的变量 `a` 会在闭包创建时用闭包外的变量 `a` 的值来初始化,除此之外它们并无其他联系。这意味着在闭包创建后,改变某个 `a` 的值都不会对另一个 `a` 的值造成任何影响。与此相反,闭包内外都是同一个变量 `b`,因此在闭包外改变其值,闭包内的值也会受影响。
|
||||
@ -461,7 +461,7 @@ let closure = { [x] in
|
||||
x.value = 10
|
||||
y.value = 10
|
||||
closure()
|
||||
// 打印 “10 10”
|
||||
// 打印“10 10”
|
||||
```
|
||||
|
||||
如果捕获列表中的值是类类型,你可以使用 `weak` 或者 `unowned` 来修饰它,闭包会分别用弱引用和无主引用来捕获该值。
|
||||
@ -698,7 +698,7 @@ class SomeSubClass: SomeSuperClass {
|
||||
let initializer: Int -> String = String.init
|
||||
let oneTwoThree = [1, 2, 3].map(initializer).reduce("", combine: +)
|
||||
print(oneTwoThree)
|
||||
// 打印 “123”
|
||||
// 打印“123”
|
||||
```
|
||||
|
||||
如果通过名字来指定某个类型,可以不用构造器表达式而直接使用类型的构造器。在其他情况下,你必须使用构造器表达式。
|
||||
|
||||
@ -477,9 +477,9 @@ func f() {
|
||||
defer { print("Third") }
|
||||
}
|
||||
f()
|
||||
// 打印 “Third”
|
||||
// 打印 “Second”
|
||||
// 打印 “First”
|
||||
// 打印“Third”
|
||||
// 打印“Second”
|
||||
// 打印“First”
|
||||
```
|
||||
|
||||
`defer` 语句中的语句无法将控制权转移到 `defer` 语句外部。
|
||||
|
||||
@ -166,9 +166,9 @@ let (firstNumber, secondNumber) = (10, 42)
|
||||
|
||||
```swift
|
||||
print("The first number is \(firstNumber).")
|
||||
// 打印 “The first number is 10.”
|
||||
// 打印“The first number is 10.”
|
||||
print("The second number is \(secondNumber).")
|
||||
// 打印 “The second number is 42.”
|
||||
// 打印“The second number is 42.”
|
||||
```
|
||||
|
||||
当常量名称的类型(`:` 类型)可以被推断出时,类型标注在常量声明中是可选的,正如 [类型推断](03_Types.html#type_inference) 中所描述的。
|
||||
@ -479,7 +479,7 @@ var x = 10
|
||||
let f = outer(&x)
|
||||
f()
|
||||
print(x)
|
||||
// 打印 “10”
|
||||
// 打印“10”
|
||||
```
|
||||
|
||||
调用嵌套函数 `inner()` 对 `a` 递增后,`x` 的值并未发生改变,因为 `inner()` 在外层函数 `outer()` 返回后才被调用。若要改变 `x` 的值,必须在 `outer()` 返回前调用 `inner()`。
|
||||
|
||||
@ -93,7 +93,7 @@ switch point {
|
||||
case let (x, y):
|
||||
print("The point is at (\(x), \(y)).")
|
||||
}
|
||||
// 打印 “The point is at (3, 2).”
|
||||
// 打印“The point is at (3, 2).”
|
||||
```
|
||||
|
||||
在上面这个例子中,`let` 会分配到元组模式 `(x, y)` 中的各个标识符模式。因此,`switch` 语句中 `case let (x, y):` 和 `case (let x, let y):` 的匹配效果是一样的。
|
||||
@ -227,7 +227,7 @@ case (-2...2, -2...2):
|
||||
default:
|
||||
print("The point is at (\(point.0), \(point.1)).")
|
||||
}
|
||||
// 打印 “(1, 2) is near the origin.”
|
||||
// 打印“(1, 2) is near the origin.”
|
||||
```
|
||||
|
||||
你可以重载 `~=` 运算符来提供自定义的表达式匹配行为。比如你可以重写上面的例子,将 `point` 表达式与字符串形式表示的点进行比较。
|
||||
@ -244,7 +244,7 @@ case ("0", "0"):
|
||||
default:
|
||||
print("The point is at (\(point.0), \(point.1)).")
|
||||
}
|
||||
// 打印 “The point is at (1, 2).”
|
||||
// 打印“The point is at (1, 2).”
|
||||
```
|
||||
|
||||
> 表达式模式语法
|
||||
|
||||
Reference in New Issue
Block a user