★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公眾號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/9711470.html
➤如果鏈接不是山青詠芝的博客園地址,則可能是爬取作者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持作者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
傳統建議使用新語言的第一個程序應打印“ Hello,world!”字樣。屏幕上。在Swift中,這可以單行完成:
- print("Hello, world!")
- // Prints "Hello, world!"
如果您使用C或Objective-C編寫代碼,則此語法看起來很熟悉-在Swift中,這行代碼是完整的程序。您無需導入單獨的庫即可實現輸入/輸出或字符串處理等功能。在全局范圍內編寫的代碼用作程序的入口點,因此您不需要main()
功能。您也不需要在每個語句的末尾寫分號。
本教程通過向您展示如何完成各種編程任務,為您提供了足夠的信息來開始在Swift中編寫代碼。如果您不了解某些內容,請不要擔心,本教程的其余部分將詳細介紹本教程中介紹的所有內容。
簡單的價值觀
使用let
做一個常數,var
使一個變量。常量的值不需要在編譯時就知道,但是您必須為它賦值一次。這意味着您可以使用常量來命名一次確定但在許多地方使用的值。
- var myVariable = 42
- myVariable = 50
- let myConstant = 42
常量或變量的類型必須與要分配給它的值的類型相同。但是,您不必總是顯式地編寫類型。在創建常量或變量時提供一個值,可使編譯器推斷其類型。在上面的示例中,編譯器將其推斷myVariable
為整數,因為其初始值為整數。
如果初始值不能提供足夠的信息(或者沒有初始值),請通過在變量后寫一個類型(用冒號分隔)來指定類型。
- let implicitInteger = 70
- let implicitDouble = 70.0
- let explicitDouble: Double = 70
實驗
創建一個顯式類型為Float
且值為的常數4
。
值永遠不會隱式轉換為另一種類型。如果需要將值轉換為其他類型,請顯式創建所需類型的實例。
- let label = "The width is "
- let width = 94
- let widthLabel = label + String(width)
實驗
嘗試String
從最后一行刪除到的轉換。你得到什么錯誤?
有一種甚至更簡單的方法可以在字符串中包含值:在括號中寫值,並在括號\
前寫反斜杠()。例如:
- let apples = 3
- let oranges = 5
- let appleSummary = "I have \(apples) apples."
- let fruitSummary = "I have \(apples + oranges) pieces of fruit."
實驗
用於\()
在字符串中包含浮點計算,並在問候語中包含某人的姓名。
"""
對於占用多行的字符串,請使用三個雙引號()。只要每個引用行的縮進都與右引號的縮進匹配,就將其刪除。例如:
- let quotation = """
- I said "I have \(apples) apples."
- And then I said "I have \(apples + oranges) pieces of fruit."
- """
使用方括號([]
)創建數組和字典,並通過在方括號中寫入索引或鍵來訪問其元素。最后一個元素后允許使用逗號。
- var shoppingList = ["catfish", "water", "tulips"]
- shoppingList[1] = "bottle of water"
- var occupations = [
- "Malcolm": "Captain",
- "Kaylee": "Mechanic",
- ]
- occupations["Jayne"] = "Public Relations"
數組隨着添加元素而自動增長。
- shoppingList.append("blue paint")
- print(shoppingList)
要創建一個空數組或字典,請使用初始化程序語法。
- let emptyArray = [String]()
- let emptyDictionary = [String: Float]()
如果可以推斷類型信息,則可以將空數組寫為[]
,將空字典寫為,[:]
例如,當您為變量設置新值或將參數傳遞給函數時。
- shoppingList = []
- occupations = [:]
控制流
使用if
和switch
制作條件語句和使用for
- in
,while
和repeat
- while
進行循環。條件或循環變量的括號是可選的。身體周圍需要支撐。
- let individualScores = [75, 43, 103, 87, 12]
- var teamScore = 0
- for score in individualScores {
- if score > 50 {
- teamScore += 3
- } else {
- teamScore += 1
- }
- }
- print(teamScore)
- // Prints "11"
在一條if
語句中,條件必須是布爾表達式-這意味着諸如之類的代碼是錯誤,而不是與零的隱式比較。if score { ... }
您可以使用if
和let
一起使用可能缺少的值。這些值表示為可選值。可選值包含一個值或包含nil
一個指示值丟失的值。?
在值的類型后寫一個問號(),以將該值標記為可選。
- var optionalString: String? = "Hello"
- print(optionalString == nil)
- // Prints "false"
- var optionalName: String? = "John Appleseed"
- var greeting = "Hello!"
- if let name = optionalName {
- greeting = "Hello, \(name)"
- }
實驗
更改optionalName
為nil
。你得到什么問候?添加一個else
設置為optionalName
is 的其他問候語的子句nil
。
如果可選值為nil
,則條件為,false
並且括號中的代碼將被跳過。否則,將解壓縮可選值,並將其分配給之后的常量let
,這將使解壓縮后的值在代碼塊內可用。
處理可選值的另一種方法是使用??
運算符提供默認值。如果缺少可選值,則使用默認值。
- let nickname: String? = nil
- let fullName: String = "John Appleseed"
- let informalGreeting = "Hi \(nickname ?? fullName)"
開關支持任何類型的數據和各種比較操作-它們不限於整數和相等性測試。
- let vegetable = "red pepper"
- switch vegetable {
- case "celery":
- print("Add some raisins and make ants on a log.")
- case "cucumber", "watercress":
- print("That would make a good tea sandwich.")
- case let x where x.hasSuffix("pepper"):
- print("Is it a spicy \(x)?")
- default:
- print("Everything tastes good in soup.")
- }
- // Prints "Is it a spicy red pepper?"
實驗
嘗試刪除默認情況。你得到什么錯誤?
注意如何let
在模式中使用它來將與模式匹配的值分配給常量。
在匹配的switch case中執行代碼后,程序將從switch語句退出。執行不會繼續到下一個案例,因此無需在每個案例代碼的末尾顯式地退出開關。
您可以使用for
- in
通過為每個鍵值對提供一對名稱來迭代字典中的項目。字典是無序集合,因此它們的鍵和值以任意順序進行迭代。
- let interestingNumbers = [
- "Prime": [2, 3, 5, 7, 11, 13],
- "Fibonacci": [1, 1, 2, 3, 5, 8],
- "Square": [1, 4, 9, 16, 25],
- ]
- var largest = 0
- for (kind, numbers) in interestingNumbers {
- for number in numbers {
- if number > largest {
- largest = number
- }
- }
- }
- print(largest)
- // Prints "25"
實驗
添加另一個變量以跟蹤最大數量的數字以及最大數量的數字。
使用while
重復的代碼塊,直到病情變化。循環的條件可以在末尾,以確保循環至少運行一次。
- var n = 2
- while n < 100 {
- n *= 2
- }
- print(n)
- // Prints "128"
- var m = 2
- repeat {
- m *= 2
- } while m < 100
- print(m)
- // Prints "128"
您可以通過使用..<
創建一系列索引來使索引保持循環。
- var total = 0
- for i in 0..<4 {
- total += i
- }
- print(total)
- // Prints "6"
使用..<
做出各種省略了其上限值和使用...
,使既包括值的范圍。
功能和關閉
使用func
聲明函數。通過在函數名稱后加上括號中的參數列表來調用該函數。使用->
的參數名稱和類型從函數的返回類型分開。
- func greet(person: String, day: String) -> String {
- return "Hello \(person), today is \(day)."
- }
- greet(person: "Bob", day: "Tuesday")
實驗
刪除day
參數。添加一個參數以在問候語中包括今天的特色午餐。
默認情況下,函數使用其參數名稱作為其參數的標簽。在參數名稱前寫一個自定義參數標簽,或寫_
為不使用任何參數標簽。
- func greet(_ person: String, on day: String) -> String {
- return "Hello \(person), today is \(day)."
- }
- greet("John", on: "Wednesday")
使用元組生成復合值,例如,從函數返回多個值。元組的元素可以通過名稱或數字來引用。
- func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
- var min = scores[0]
- var max = scores[0]
- var sum = 0
- for score in scores {
- if score > max {
- max = score
- } else if score < min {
- min = score
- }
- sum += score
- }
- return (min, max, sum)
- }
- let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9])
- print(statistics.sum)
- // Prints "120"
- print(statistics.2)
- // Prints "120"
函數可以嵌套。嵌套函數可以訪問在外部函數中聲明的變量。您可以使用嵌套函數將代碼組織為長函數或復雜函數。
- func returnFifteen() -> Int {
- var y = 10
- func add() {
- y += 5
- }
- add()
- return y
- }
- returnFifteen()
函數是一流的類型。這意味着一個函數可以返回另一個函數作為其值。
- func makeIncrementer() -> ((Int) -> Int) {
- func addOne(number: Int) -> Int {
- return 1 + number
- }
- return addOne
- }
- var increment = makeIncrementer()
- increment(7)
一個函數可以將另一個函數作為其參數之一。
- func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
- for item in list {
- if condition(item) {
- return true
- }
- }
- return false
- }
- func lessThanTen(number: Int) -> Bool {
- return number < 10
- }
- var numbers = [20, 19, 7, 12]
- hasAnyMatches(list: numbers, condition: lessThanTen)
函數實際上是閉包的一種特殊情況:可以稍后調用的代碼塊。閉包中的代碼可以訪問在創建閉包的作用域中可用的變量和函數,即使該閉包在執行時位於不同的作用域中—您已經看到了嵌套函數的示例。您可以使用大括號({}
)將代碼括起來,從而編寫一個沒有名稱的閉包。使用in
的參數和返回類型從身體分離。
- numbers.map({ (number: Int) -> Int in
- let result = 3 * number
- return result
- })
實驗
重寫閉包以對所有奇數返回零。
您有幾種選擇可以更簡潔地編寫閉包。當已知閉包的類型(例如委托的回調)時,可以省略其參數的類型,返回類型或兩者。單條語句閉包隱式返回其唯一語句的值。
- let mappedNumbers = numbers.map({ number in 3 * number })
- print(mappedNumbers)
- // Prints "[60, 57, 21, 36]"
您可以通過數字而不是名稱來引用參數-這種方法在很短的閉包中特別有用。作為最后一個參數傳遞給函數的閉包可以在括號后立即顯示。如果閉包是函數的唯一參數,則可以完全省略括號。
- let sortedNumbers = numbers.sorted { $0 > $1 }
- print(sortedNumbers)
- // Prints "[20, 19, 12, 7]"
對象和類
使用class
后跟類的名稱來創建一個類。類中的屬性聲明與常量或變量聲明的編寫方式相同,只不過它是在類的上下文中編寫的。同樣,方法和函數聲明的編寫方式相同。
- class Shape {
- var numberOfSides = 0
- func simpleDescription() -> String {
- return "A shape with \(numberOfSides) sides."
- }
- }
實驗
用添加一個常量屬性let
,並添加另一個帶有參數的方法。
通過在類名稱后加上括號來創建類的實例。使用點語法訪問實例的屬性和方法。
- var shape = Shape()
- shape.numberOfSides = 7
- var shapeDescription = shape.simpleDescription()
Shape
該類的版本缺少重要的內容:創建實例時用於設置類的初始化程序。使用init
創建一個。
- class NamedShape {
- var numberOfSides: Int = 0
- var name: String
- init(name: String) {
- self.name = name
- }
- func simpleDescription() -> String {
- return "A shape with \(numberOfSides) sides."
- }
- }
注意如何self
使用name
屬性來區分屬性和name
初始化程序的參數。創建類的實例時,初始化函數的參數像函數調用一樣傳遞。每個屬性都需要在其聲明中(如numberOfSides
)或在初始化程序中(如name
)分配一個值。
deinit
如果需要在釋放對象之前執行一些清理,請使用來創建一個反初始化程序。
子類在其類名之后包括其超類名,並用冒號分隔。不需要類繼承任何標准根類,因此您可以根據需要包含或忽略超類。
覆蓋超類的實現的子類上override
的方法標記為—偶然覆蓋方法,不帶override
,編譯器將其檢測為錯誤。編譯器還會檢測override
那些實際上沒有覆蓋超類中任何方法的方法。
- class Square: NamedShape {
- var sideLength: Double
- init(sideLength: Double, name: String) {
- self.sideLength = sideLength
- super.init(name: name)
- numberOfSides = 4
- }
- func area() -> Double {
- return sideLength * sideLength
- }
- override func simpleDescription() -> String {
- return "A square with sides of length \(sideLength)."
- }
- }
- let test = Square(sideLength: 5.2, name: "my test square")
- test.area()
- test.simpleDescription()
實驗
再創建一個NamedShape
名為的子類,Circle
它以半徑和名稱作為其初始值設定項的參數。在類上實現area()
和simpleDescription()
方法Circle
。
除了存儲的簡單屬性外,屬性還可以具有getter和setter。
- class EquilateralTriangle: NamedShape {
- var sideLength: Double = 0.0
- init(sideLength: Double, name: String) {
- self.sideLength = sideLength
- super.init(name: name)
- numberOfSides = 3
- }
- var perimeter: Double {
- get {
- return 3.0 * sideLength
- }
- set {
- sideLength = newValue / 3.0
- }
- }
- override func simpleDescription() -> String {
- return "An equilateral triangle with sides of length \(sideLength)."
- }
- }
- var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
- print(triangle.perimeter)
- // Prints "9.3"
- triangle.perimeter = 9.9
- print(triangle.sideLength)
- // Prints "3.3000000000000003"
在for的setter中perimeter
,新值具有隱式名稱newValue
。您可以在后面的括號中提供一個明確的名稱set
。
請注意,EquilateralTriangle
該類的初始化程序具有三個不同的步驟:
- 設置子類聲明的屬性的值。
- 調用超類的初始化程序。
- 更改超類定義的屬性的值。此時還可以完成使用方法,getter或setter的任何其他設置工作。
如果您不需要計算屬性,但仍然需要提供在設置新值之前和之后運行的代碼,請使用willSet
和didSet
。只要提供的代碼在初始化程序之外更改,就可以運行您提供的代碼。例如,下面的類確保其三角形的邊長始終與其正方形的邊長相同。
- class TriangleAndSquare {
- var triangle: EquilateralTriangle {
- willSet {
- square.sideLength = newValue.sideLength
- }
- }
- var square: Square {
- willSet {
- triangle.sideLength = newValue.sideLength
- }
- }
- init(size: Double, name: String) {
- square = Square(sideLength: size, name: name)
- triangle = EquilateralTriangle(sideLength: size, name: name)
- }
- }
- var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
- print(triangleAndSquare.square.sideLength)
- // Prints "10.0"
- print(triangleAndSquare.triangle.sideLength)
- // Prints "10.0"
- triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
- print(triangleAndSquare.triangle.sideLength)
- // Prints "50.0"
使用可選值時,可以?
在方法,屬性和下標之類的操作之前編寫。如果之前的值?
是nil
,則后面的一切都會?
被忽略,整個表達式的值是nil
。否則,將取消包裝可選值,並且所有操作之后的內容都將?
被包裝。在這兩種情況下,整個表達式的值都是一個可選值。
- let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
- let sideLength = optionalSquare?.sideLength
枚舉和結構
使用enum
創建一個枚舉。像類和所有其他命名類型一樣,枚舉可以具有與之關聯的方法。
- enum Rank: Int {
- case ace = 1
- case two, three, four, five, six, seven, eight, nine, ten
- case jack, queen, king
- func simpleDescription() -> String {
- switch self {
- case .ace:
- return "ace"
- case .jack:
- return "jack"
- case .queen:
- return "queen"
- case .king:
- return "king"
- default:
- return String(self.rawValue)
- }
- }
- }
- let ace = Rank.ace
- let aceRawValue = ace.rawValue
實驗
編寫一個通過比較兩個Rank
原始值來比較兩個值的函數。
默認情況下,Swift分配的原始值從零開始,每次遞增1,但是您可以通過顯式指定值來更改此行為。在上面的示例中,Ace
顯式指定了的原始值1
,其余原始值按順序分配。您還可以使用字符串或浮點數作為枚舉的原始類型。使用該rawValue
屬性訪問枚舉案例的原始值。
使用init?(rawValue:)
初始化程序從原始值創建枚舉的實例。它返回任一枚舉的情況下的匹配的原始值或nil
如果不存在匹配Rank
。
- if let convertedRank = Rank(rawValue: 3) {
- let threeDescription = convertedRank.simpleDescription()
- }
枚舉的大小寫值是實際值,而不僅僅是寫原始值的另一種方法。實際上,在沒有有意義的原始價值的情況下,您不必提供原始價值。
- enum Suit {
- case spades, hearts, diamonds, clubs
- func simpleDescription() -> String {
- switch self {
- case .spades:
- return "spades"
- case .hearts:
- return "hearts"
- case .diamonds:
- return "diamonds"
- case .clubs:
- return "clubs"
- }
- }
- }
- let hearts = Suit.hearts
- let heartsDescription = hearts.simpleDescription()
實驗
添加一個color()
方法Suit
,對於黑桃和球棒返回“黑色”,對於心形和菱形返回“紅色”。
請注意hearts
上面引用枚舉大小寫的兩種方式:為hearts
常量分配值時,枚舉大小寫Suit.hearts
以其全名引用,因為常量沒有指定顯式類型。在交換機內部,枚舉用縮寫形式表示,.hearts
因為self
已知的值是合適的。只要知道值的類型,就可以使用縮寫形式。
如果枚舉具有原始值,則將這些值確定為聲明的一部分,這意味着特定枚舉用例的每個實例始終具有相同的原始值。枚舉用例的另一種選擇是具有與用例關聯的值-這些值是在創建實例時確定的,並且對於枚舉用例的每個實例而言,它們可能是不同的。您可以將關聯的值視為枚舉案例實例的存儲屬性。例如,考慮從服務器請求日出和日落時間的情況。服務器要么以請求的信息作為響應,要么以錯誤的描述作為響應。
- enum ServerResponse {
- case result(String, String)
- case failure(String)
- }
- let success = ServerResponse.result("6:00 am", "8:09 pm")
- let failure = ServerResponse.failure("Out of cheese.")
- switch success {
- case let .result(sunrise, sunset):
- print("Sunrise is at \(sunrise) and sunset is at \(sunset).")
- case let .failure(message):
- print("Failure... \(message)")
- }
- // Prints "Sunrise is at 6:00 am and sunset is at 8:09 pm."
實驗
ServerResponse
在交換機和交換機之間添加第三種情況。
請注意,如何將ServerResponse
值從日出時間和日落時間中提取出來,作為將值與轉換案例進行匹配的一部分。
使用struct
創建的結構。結構支持許多與類相同的行為,包括方法和初始化程序。結構和類之間最重要的區別之一是,結構在代碼中傳遞時始終會被復制,而類是通過引用傳遞的。
- struct Card {
- var rank: Rank
- var suit: Suit
- func simpleDescription() -> String {
- return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
- }
- }
- let threeOfSpades = Card(rank: .three, suit: .spades)
- let threeOfSpadesDescription = threeOfSpades.simpleDescription()
實驗
編寫一個函數,該函數返回一個包含一整套紙牌的數組,每個紙牌的等級和西裝組合各一張。
協議和擴展
使用protocol
申報的協議。
- protocol ExampleProtocol {
- var simpleDescription: String { get }
- mutating func adjust()
- }
類,枚舉和結構都可以采用協議。
- class SimpleClass: ExampleProtocol {
- var simpleDescription: String = "A very simple class."
- var anotherProperty: Int = 69105
- func adjust() {
- simpleDescription += " Now 100% adjusted."
- }
- }
- var a = SimpleClass()
- a.adjust()
- let aDescription = a.simpleDescription
- struct SimpleStructure: ExampleProtocol {
- var simpleDescription: String = "A simple structure"
- mutating func adjust() {
- simpleDescription += " (adjusted)"
- }
- }
- var b = SimpleStructure()
- b.adjust()
- let bDescription = b.simpleDescription
實驗
向添加新的要求ExampleProtocol
。你需要什么樣的變化做出SimpleClass
和SimpleStructure
使他們仍然符合協議?
請注意,mutating
在的聲明中使用了關鍵字SimpleStructure
來標記修改結構的方法。的聲明SimpleClass
不需要其任何標記為變異的方法,因為類上的方法始終可以修改該類。
用於extension
向現有類型添加功能,例如新方法和計算屬性。您可以使用擴展將協議一致性添加到在其他地方聲明的類型,甚至添加到從庫或框架導入的類型。
- extension Int: ExampleProtocol {
- var simpleDescription: String {
- return "The number \(self)"
- }
- mutating func adjust() {
- self += 42
- }
- }
- print(7.simpleDescription)
- // Prints "The number 7"
實驗
為Double
添加absoluteValue
屬性的類型編寫擴展名。
您可以像使用任何其他命名類型一樣使用協議名稱,例如,創建具有不同類型但都符合一個協議的對象的集合。當使用類型為協議類型的值時,協議定義之外的方法不可用。
- let protocolValue: ExampleProtocol = a
- print(protocolValue.simpleDescription)
- // Prints "A very simple class. Now 100% adjusted."
- // print(protocolValue.anotherProperty) // Uncomment to see the error
即使變量protocolValue
的運行時類型為SimpleClass
,編譯器也將其視為的給定類型ExampleProtocol
。這意味着除了協議一致性之外,您不能意外訪問該類實現的方法或屬性。
錯誤處理
您可以使用采用該Error
協議的任何類型來表示錯誤。
- enum PrinterError: Error {
- case outOfPaper
- case noToner
- case onFire
- }
使用throw
拋出一個錯誤,並throws
標記,可以拋出一個錯誤的功能。如果在函數中引發錯誤,則該函數將立即返回,並且調用該函數的代碼將處理該錯誤。
- func send(job: Int, toPrinter printerName: String) throws -> String {
- if printerName == "Never Has Toner" {
- throw PrinterError.noToner
- }
- return "Job sent"
- }
有幾種處理錯誤的方法。一種方法是使用do
- catch
。在該do
塊內部,您可以標記可能會通過try
在其前面寫入而引發錯誤的代碼。在catch
塊內,錯誤會自動命名,error
除非您給它改了名稱。
- do {
- let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")
- print(printerResponse)
- } catch {
- print(error)
- }
- // Prints "Job sent"
實驗
將打印機名稱更改為,以便該函數引發錯誤。"Never Has Toner"
send(job:toPrinter:)
您可以提供多個catch
處理特定錯誤的塊。您catch
就像case
在切換之后一樣,編寫了一個模式。
- do {
- let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")
- print(printerResponse)
- } catch PrinterError.onFire {
- print("I'll just put this over here, with the rest of the fire.")
- } catch let printerError as PrinterError {
- print("Printer error: \(printerError).")
- } catch {
- print(error)
- }
- // Prints "Job sent"
實驗
添加代碼以在do
塊內引發錯誤。您需要引發哪種錯誤,以便第一個catch
塊處理該錯誤?那第二塊和第三塊呢?
處理錯誤的另一種方法是try?
用於將結果轉換為可選的。如果函數拋出錯誤,則將丟棄特定錯誤,結果為nil
。否則,結果是一個可選值,其中包含函數返回的值。
- let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")
- let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner")
用defer
寫的是在函數中的所有其它代碼后執行代碼塊,只是在函數返回之前。無論函數是否引發錯誤,都將執行代碼。defer
即使需要在不同的時間執行設置和清除代碼,也可以使用它們彼此相鄰。
- var fridgeIsOpen = false
- let fridgeContent = ["milk", "eggs", "leftovers"]
- func fridgeContains(_ food: String) -> Bool {
- fridgeIsOpen = true
- defer {
- fridgeIsOpen = false
- }
- let result = fridgeContent.contains(food)
- return result
- }
- fridgeContains("banana")
- print(fridgeIsOpen)
- // Prints "false"
泛型
在尖括號內寫一個名稱,以構成通用函數或類型。
- func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
- var result = [Item]()
- for _ in 0..<numberOfTimes {
- result.append(item)
- }
- return result
- }
- makeArray(repeating: "knock", numberOfTimes: 4)
您可以使函數和方法以及類,枚舉和結構成為通用形式。
- // Reimplement the Swift standard library's optional type
- enum OptionalValue<Wrapped> {
- case none
- case some(Wrapped)
- }
- var possibleInteger: OptionalValue<Int> = .none
- possibleInteger = .some(100)
where
在正文前使用權利來指定需求列表,例如,要求類型實現協議,要求兩個類型相同或要求一個類具有特定的超類。
- func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool
- where T.Element: Equatable, T.Element == U.Element
- {
- for lhsItem in lhs {
- for rhsItem in rhs {
- if lhsItem == rhsItem {
- return true
- }
- }
- }
- return false
- }
- anyCommonElements([1, 2, 3], [3])
實驗
修改該anyCommonElements(_:_:)
函數以使該函數返回任何兩個序列共同具有的元素的數組。
寫作和寫作一樣。<T: Equatable>
<T> ... where T: Equatable