Swift第二周學(xué)習(xí)總結(jié)

Swift總結(jié)

一、字典(dictionary)

1.字典:存放鍵值對組合的容器。
2.字典中的每個元素都有兩部分構(gòu)成,冒號前面是鍵冒號后面是值。
var dict: [String: String] = ["abacus": "算盤","abnormal": "異常的"]
3.通過鍵可以獲取對應(yīng)的值(可空類型,因?yàn)榻o的鍵有可能沒有與之對應(yīng)的值)
print(dict["hello"]!)
4.對元素的操作
?添加元素:dict["delicious"] = "好吃的"
?刪除元素:dict.removeValueForKey("hello")或dict["hello"] = nil
?修改元素:dict["abnormal"] = "牛糞"
?遍歷字典中所有的值:for value in dict.values { print(value) }
?遍歷字典中所有的鍵:for key in dict.keys { print("\(key) ---> \(dict[key])") }注意結(jié)果是這樣的:abacus ---> Optional("算盤")dict[key]為可空類型
?直接通過一個元組獲得字典中的鍵和值(原始類型):for (key, value) in dict { print("\(key) ---> \(value)") }現(xiàn)在結(jié)果是這樣的:abacus ---> 算盤


二、集合(sets)

1.定義兩個集合:var a: Set<Int> = [1, 2, 3, 1, 2, 5] var b: Set<Int> = [3, 5, 7, 9, 11]集合會去掉重復(fù)的元素.
2.添加元素:a.insert(100)
3.刪除元素:a.remove(2)
4.交集:a.intersect(b)
5.并集:a.union(b)
6.差集:a.subtract(b)
7.判斷b是不是a的子集:b.isSubsetOf(a)
8.判斷a是不是c的超集:a.isSupersetOf(c)


三、函數(shù)(function)

1.定義函數(shù):func 函數(shù)名(參數(shù)列表)-> 返回類型{函數(shù)的執(zhí)行}
★Swift中函數(shù)的參數(shù)可以設(shè)置默認(rèn)值,如果調(diào)用函數(shù)時沒有給參數(shù)賦值就直接使用默認(rèn)值

func sayHello(personName: String,_ alreadyGreeted: Bool = false) -> String{
    if alreadyGreeted{
        return "怎么又是你," + personName + "!"
    }else {
        return "你好" + personName + "!"
    }
}

2.調(diào)用函數(shù)
★調(diào)用Swift的函數(shù)時,在默認(rèn)情況下從第二個參數(shù)開始需要寫參數(shù)名
print(sayHello("rose"))
3.函數(shù)的參數(shù)名
函數(shù)名(外部參數(shù)名 內(nèi)部參數(shù)名: 類型,外部參數(shù)名 內(nèi)部參數(shù)名:類型)
★如果不寫外部參數(shù)名那么內(nèi)部參數(shù)名也是外部參數(shù)名,可以使用_來省略外部參數(shù)名

func myMin(a x: Int, b y: Int) -> Int{
    return x < y ? x : y
}
//調(diào)用函數(shù)時要用函數(shù)的外部參數(shù)名
print(myMin(a: 3, b: 5))

★Swift中函數(shù)的參數(shù)列表可以是可變參數(shù)列表

func sum(nums: Int...) -> Int{
    var total = 0
    for num in nums{
        total += num
    }
    return total
}
print(sum( ))    //結(jié)果為0
print(sum(999))  //結(jié)果為999
print(sum(1,2,3,4))     //結(jié)果為10

★可以使用元組讓函數(shù)一次返回多條數(shù)據(jù)
下面這個函數(shù)參數(shù)是一個數(shù)組,函數(shù)的功能是找出最大值、最小值并用一個元組返回

func minMax(array: [Int]) -> (min: Int, max: Int) {
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

let b = minMax([12,45,23,89,156,55,38])
print(b.min)    //print(b.0)
print(b.max)    //print(b.1)

★inout - 輸入輸出參數(shù)(不僅將數(shù)據(jù)傳人函數(shù)還要從函數(shù)中取出數(shù)據(jù))

func createX(inout x: Int) {
    x = 1000
}

var x = 1
//使用inout 要加&
createX(&x)
print(x)

例1.//設(shè)計一個函數(shù)傳入兩個整數(shù)m和n,計算m到n的和

func figure( m: Int,n: Int) -> Int{
    let (a,b) = m > n ? (n,m) : (m,n)
    var sum = 0
    for i in a...b{
        sum += i
    }
    return sum
}
print(figure(3, n: 50))

4.函數(shù)的遞歸調(diào)用(一個函數(shù)直接或間接的調(diào)用自身)

  • 遞歸公式
  • 收斂條件

例2.設(shè)計一個函數(shù)計算組合數(shù)C(m,n) = m!/n!/(m-n)!

func combine(m: Int,_ n: Int) -> Int{
    let (a,b) = m > n ? (m,n) : (n,m)
//assert (m >= n ,"m必須大于等于n")  //斷言
    let comb = f(a) / f(b) / f((a - b))
    return comb
}

階乘(使用了遞歸調(diào)用)
func f(n: Int ) -> Int{
    if n == 0 || n == 1{
        return 1
    }
    return n * f(n - 1)
}
print(combine(5, 3))

5.函數(shù)也可以作為另一個函數(shù)的參數(shù)或返回值
例如:

func foo(array: [Int], fn: (Int, Int) -> Int) -> Int {  return Int      }

那么當(dāng)調(diào)用foo函數(shù)時第二個參數(shù)可以傳什么?

  • 所有自定義的(Int, Int) -> Int類型的函數(shù)
  • 傳入已有的二元運(yùn)算符: +-*/%(因?yàn)檫\(yùn)算符也是函數(shù))
  • 傳入匿名函數(shù)(閉包):
1.完整的閉包寫法
print(foo(a, fn: { (a, b) -> Int in
    return a + b
}))
2.省略掉類型和不必要的括號
print(foo(a, fn: { a, b in a + b }))
3.省略參數(shù)名
print(foo(a, fn: { $0 + $1 }))
4.尾隨閉包
print(foo(a) { (a, b) -> Int in
    return a + b
})
print(foo(a) { $0 + $1 })
  • 尾隨閉包:
    1.如果函數(shù)的最后一個參數(shù)是閉包可以寫成尾隨閉包的形式,也就是將閉包放到函數(shù)參數(shù)的圓括號外面寫在一對花括號中
    2.如果函數(shù)后面有尾隨閉包且函數(shù)的圓括號中沒有參數(shù),那么函數(shù)的圓括號也可以省略(僅限于有尾隨閉包的場景)
var array = ["game","abacus","hello","cat","good","honey","shit","young","xman"]
array.sortInPlace() { $0 > $1}
print(array) 
array.sortInPlace { $0 > $1}
print(array)
//結(jié)果一樣:["young", "xman", "shit", "honey", "hello", "good", "game", "cat", "abacus"]
★數(shù)組(增加三種方法)

let array = [23,56,12,96,85,26,15,45]
1.過濾

let newArray = array.filter { $0 > 50 } //過濾掉小于50的元素
let Array = array.filter { (x: Int) -> Bool in
    return x % 2 == 0} //過濾掉奇數(shù),剩下偶數(shù)

2.映射

let newArray2 = array.map { (x: Int) -> Int in
    return x * x // {$0 * $0}
}

3.縮減

let newArray3 = array.reduce(0, combine: +)
// 數(shù)組各元素相加,初始值為0
let newArray4 = array.reduce(1, combine: *)
//數(shù)組各元素相乘,初始值為1
let newArray5 = array.reduce(array[0]) {$1 > $0 ? $1 : $0 }
//找出數(shù)組里面最大的數(shù)

四、類(class)

1.如何創(chuàng)建一個類,和怎么調(diào)用類的方法?

我們創(chuàng)建一個Student類來說明:

  • 定義類

  • 數(shù)據(jù)抽象(屬性)

    • 存儲屬性(保存相關(guān)的數(shù)據(jù)的屬性)
    • 計算屬性(通過對儲存屬性做運(yùn)算得到的屬性)
  • 行為抽象(方法)

  • 初始化方法(我們可以在一個類中定義多個初始化方法)

    • 指派初始化方法/指派構(gòu)造器(被其他初始化方法調(diào)用的初始化方法)
    • 便利初始化方法/便利構(gòu)造器(調(diào)用了其它初始化方法的初始化方法)
  • 訪問修飾符

  • public(公開)

  • internal(內(nèi)部的) - 默認(rèn)

  • private(私有)

  • 步驟1: 定義類(如果你要用的類蘋果已經(jīng)提供了就直接進(jìn)入第2步)
    //定義類就可以創(chuàng)建出新的類型
    //學(xué)生類
class Student {
    // 變量定義到類的外面就叫變量 - variable
    // 變量定義到類的里面就叫屬性 - property
    // 數(shù)據(jù)抽象 - 找到和學(xué)生相關(guān)的屬性(找名詞)
    var name: String
    var age: Int
    // 初始化方法(構(gòu)造方法/構(gòu)造器) - constructor
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    // 函數(shù)寫到類的外面就叫函數(shù) - function
    // 函數(shù)寫到類的里面就叫方法 - method
    // 行為抽象 - 找到和學(xué)生相關(guān)的方法(找動詞)
    func eat() {
        print("\(name)正在吃飯.")
    }
    func study(courseName: String) {
        print("\(name)正在學(xué)習(xí)\(courseName).")
    }
  • 步驟2: 創(chuàng)建對象(調(diào)用初始化方法)
let stu1 = Student(name: "王鋼蛋", age: 21)
  • 步驟3: 給對象發(fā)消息(通過給對象發(fā)消息來解決問題)
stu1.eat()
stu1.study("Swift程序設(shè)計")

例3.用面向?qū)ο蟮姆绞綄懖聰?shù)字游戲
首先建一個機(jī)器人的類

class Robot{
    var answer: Int //正確答案
    var counter: Int = 0 //猜的次數(shù)
    var hint: String //提示信息
    //初始化方法應(yīng)該保證所有的存儲屬性都被初始化(有值)
    init(){
        answer = Int(arc4random_uniform(100)) + 1
        //counter = 0
        hint = ""
    }
    //行為抽象
    //判斷
    func judge(thyAnswer: Int) -> Bool{
        counter += 1
        if thyAnswer < answer{
            hint = "大一點(diǎn)"
        }else if thyAnswer > answer{
            hint = "小一點(diǎn)"
        }else{
            hint = "恭喜你猜對了!你總共猜了\(counter)次"
            return true
        }
        return false
    }
}

然后創(chuàng)建對象,面向?qū)ο缶幊?/p>

let r = Robot()
var isGameOver = false
repeat{
    print("請輸入你猜的數(shù)字:",terminator: "")
    let thyAnswer = inputInt()
    isGameOver = r.judge(thyAnswer)
    print(r.hint)
}while !isGameOver
if r.counter > 7{
    print("智商感人!")
}
2.類的擴(kuò)展
  • 如果在某個特定的應(yīng)用場景中你發(fā)現(xiàn)你的類缺少了某項(xiàng)功能
  • 那么可以通過擴(kuò)展(extension)的方式現(xiàn)場添加這項(xiàng)功能
extension Point{
    var cgPoint: CGPoint{
        get{return CGPointMake(CGFloat(X), CGFloat(Y))}
    }
}
//用Double類型的點(diǎn)(X,Y),構(gòu)造CGFloat類型的點(diǎn)
3.級聯(lián)編程和重載函數(shù)

例4.計算分?jǐn)?shù)(化簡和正規(guī)化)

//找最大公約數(shù)
func gcd(x: Int, _ y: Int) -> Int{
    if x > y {
        return gcd(y, x)
    }else if y % x != 0{
        return gcd(y % x, x)//函數(shù)的遞歸調(diào)用
    }else {
        return x
    }
}
class Fraction {
 //存儲屬性通常是private的,因?yàn)閿?shù)據(jù)要保護(hù)起來
 //方法一般是public的,因?yàn)榉椒ㄊ菍ο蠼邮艿南? //如果自定義的類沒有打算在其他項(xiàng)目中使用,可以不寫訪問修飾符
 //直接使用默認(rèn)的internal修飾符表示在本項(xiàng)目中公開對其他項(xiàng)目私有
    private var _num: Int
    private var _den: Int
 //計算屬性
    var info: String{
        get{
            return _num == 0 || _den == 1 ? "\(_num)" : "\(_num)/\(_den)"}
    }
    init (num: Int, den: Int){
        _num = num
        _den = den
        simplify()
        normalIze()
    }

    func add(other: Fraction) -> Fraction{
        return Fraction(num: _num * other._den + other._num * _den, den: _den * other._den).simplify().normalIze()//級聯(lián)編程
          }
    func sub(other: Fraction) -> Fraction{
        return Fraction(num: _num * other._den - other._num * _den, den: _den * other._den).simplify().normalIze()
    }
    func mul(other: Fraction) -> Fraction{
        return Fraction(num: _num * other._num, den: _den * other._den).simplify().normalIze()
}
    func div(other:Fraction) -> Fraction{
        return Fraction(num: _num * other._den, den: _den * other._num).simplify().normalIze()
    }
    //正規(guī)化
    func normalIze() -> Fraction{
        if _den < 0{
            _num = -_num
            _den = -_den
        }
        return self
    }
    //化簡
    func simplify() -> Fraction{
        if _num == 0{
            _den = 1
        }
        else {
            let x = abs(_num)
            let y = abs(_den)
            let g = gcd(x, y)
            _num /= g
            _den /= g
        }
        return self
    }
}
//運(yùn)算符重載(為自定義的類型定義運(yùn)算符)
func + (one: Fraction, two: Fraction) -> Fraction {
    return one.add(two)
}
//用+號重新定義加法(add)運(yùn)算
func - (one: Fraction, two: Fraction) -> Fraction {
    return one.sub(two)
}
func * (one: Fraction, two: Fraction) -> Fraction {
    return one.mul(two)
}
func / (one: Fraction, two: Fraction) -> Fraction {
    return one.div(two)
}
4.繼承和多態(tài)

1.繼承

  • 繼承:從已有的類創(chuàng)建新類的過程,提供繼承信息的類稱為父類(超類/基類)
  • 得到繼承信息的稱為子類(派生類/衍生類),通常子類除了得到父類的繼承信息還會增加一些自己特有的東西,所以子類比父類更強(qiáng)大
  • 繼承的意義在于子類可以復(fù)用父類的代碼并且著增強(qiáng)系統(tǒng)現(xiàn)有的功能

我們先建一個Pet的類(父類)

//枚舉類型
enum Gender{
    case Male
    case Female
}
class Pet {
    var nickname: String
    var gender: Gender
    var age: Int
    
    init(nickname: String, gender: Gender, age: Int){
        self.age = age
        self.gender = gender
        self.nickname = nickname
    }
    func play() {
        print("\(nickname)正在玩.")
    }
    
    func eat(){
        print("\(nickname)正在吃東西.")
    }
    
    func shout(){
        print("\(nickname)發(fā)出了叫聲.")
    }

再建一個Dog和Cat的類(Pet的子類)

class Dog: Pet {
    var isLarge: Bool
    
    init(nickname: String, gender: Gender, age: Int, isLarge: Bool) {
       self.isLarge = isLarge
        super.init(nickname: nickname, gender: gender, age: age)
    }
    func watchDoor(){
        if isLarge{
           print("\(nickname)正在看門.")
        }else{
            print("\(nickname)太小了,誰也打不過")
        }
    }
    override func shout() {
        print("\(nickname):汪汪汪...")
    }
    override func play() {
        super.play()
        print("\(nickname)正在玩球.")
    }
}
class Cat: Pet {
    var hairColor: String
//子類的初始化方法
    init(nickname: String, gender: Gender, age: Int, hairColor: String) {
       self.hairColor = hairColor
        super.init(nickname: nickname, gender: gender, age: age)
    }
    //父類有的方法子類可以重新實(shí)現(xiàn),這個方法叫做重寫
    //需要在方法前添加override關(guān)鍵字
    //重寫有時也被稱為置換/覆蓋/覆寫
    override func play() {
        super.play()
        print("\(nickname)正在玩毛線球.")
    }
    override func shout() {
        print("\(nickname):喵喵喵...")
    }
    func catchTheMouse(){
        print("\(nickname)正在抓老鼠.")
    }
}
  • 創(chuàng)建對象
let petsArray = [
    Cat(nickname: "加菲", gender: .Female, age: 6, hairColor: "gray"),
    Dog(nickname: "旺財", gender: .Male, age: 10, isLarge: true),
    Dog(nickname: "大黃", gender: .Male, age: 9, isLarge: false)
    ]

2.多態(tài)

for pet in petsArray{
    //同樣的對象類型(Pet類型)接收相同的消息(調(diào)用相同的方法)
    //但是做了不同的事情,這就是多態(tài)(polymorphism)
    //實(shí)現(xiàn)多態(tài)的關(guān)鍵步驟:
    //1.方法重寫(子類在繼承父類的過程中對父類已有的方法進(jìn)行重寫,而且不同的子類給出各自不同的實(shí)現(xiàn)版本)
    //2.對象造型(將子類對象當(dāng)成父類型來使用)
    pet.shout()
    //可以通過if + as?將父類型安全的轉(zhuǎn)換成子類型然后在調(diào)子類型特有的方法
    if let dog = pet as? Dog{
        dog.watchDoor()
    }else if let cat = pet as? Cat{
        cat.catchTheMouse()
    }else if let pig = pet as? Pig{
       pig.sleep()
    }
}
  • 如果要將父類型變量轉(zhuǎn)換成子類型需要用AS運(yùn)算符進(jìn)行類型轉(zhuǎn)換
  • 如果能夠確認(rèn)父類型的變量中就是某種子類型的對象可以用as!進(jìn)行轉(zhuǎn)換
  • 如果不能確認(rèn)父類型的變量是哪種子類型可以用as?嘗試轉(zhuǎn)換
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容