Swift第二周學習任務
一.容器類(集合,字典)
1.集合
var collectionA: Set<Int> = [2, 3, 4, 5, 1, 1, 2, 3] //[2, 3, 5, 4, 1]
collectionA.insert(100) //添加元素100到集合中
collectionA.remove(2) //刪除元素值為2的元素
var collectionB: Set<Int> = [2, 3, 1]
print(collectionA.intersect(collectionB)) //輸出兩個集合的交集
print(collectionA.union(collectionB)) //輸出兩個集合的并集
print(collectionA.subtract(collectionB)) //輸出集合A有B沒有的元素(差集)
集合存儲方式為哈希存儲,在集合內每個數都是無序的。并且每個元素值只能有且只有1個.上述集合中,集合中的元素相同的數只會被存儲一次。[2, 3, 5, 4, 1],在存儲空間中按照要求任意存放
哈希碼(hash code)/散列碼
MD5 / SHA-1 這類存儲方式一般用于大型網站上對用戶密碼的一種映射關系,將用戶的密碼進行只能夠單向的映射操作.達到加密的作用
var a: Set<Int> = [1, 2, 3, 1, 2, 5]
let c: Set<Int> = [1, 3]
print(c.isSubsetOf(a)) // 判斷c是不是a的子集
print(a.isSupersetOf(c)) // 判斷a是不是c的超集
let d: Set<Int> = [2, 1000, 10000]
print(a.isDisjointWith(d)) // 判斷兩個集合是否相交
2.字典
字典其原理就是通過一種值查找另一個值的過程。值通過字典存儲,形成鍵值對。每一個鍵值對都是唯一的,一個唯一的key對應一個value(可空)。
var dict: [String: String] = ["abacus": "算盤", "abnormal": "異常的", "hello" : "你好", "good": "好的"] // 定義一個字典
dict["haha"] = "哈哈" // 添加鍵值對,添加字典元素
dict["hello"] = nil // 刪除鍵值對,刪除字典元素
dict.removeValueForkey("hello") // 與上面方法效果一樣
dict[good] = "不好" // 修改value
字典的遍歷方式有3種,第一種遍歷字典拿到每一個key。第二種遍歷拿到每個元素的value。第三種遍歷拿到一個元組,(key, value)。
for key in dict.key {
print("\(key) -> \(dict[key])")
}
for value in dict.value {
print(value)
}
for (key, value) in dict {
print("\(key) -> \(value)")
}
二.函數
1.定義函數與基本用法
func 函數名(參數列表) ->返回類型 {函數的執行體}
Swift中函數的參數可以設定默認值
如果調用函數的時候沒有給該參數賦值就直接使用默認值
可以使用元組(tuple)讓函數一次返回多條數據
inout - 輸入輸出函數(不僅將數據傳入函數還要從函數中取出數據)
與C語言中的指針作用相似
func creatX(inout x: Int) {
x = 1000
}
var x = 1
creatX(&x)
print(x)
斷言:當程序運行到自己預先加的斷言時不成立時,程序崩潰。控制臺會打印斷言中的語句
assert(m >= n, "m必須大于等于n")
2.遞歸函數
重點:1.確定遞歸公式 2.確定收斂條件
原理:遞歸函數通過一個函數直接或間接得調用自身函數,實現函數計算功能
//求階乘
func f(n: Int) -> double {
if n == 1 && n == 0 {
return 1 //當n = 1 或者 n = 0 時,跳出遞歸公式,相當于是n * n - 1 * ... * 1,沒調用一次得到一個當前n值做乘法運算
}
return n * f(n - 1)
}
//漢諾伊塔游戲
func hanoi(n: Int, _ a: String, _ b: String, _ c: String) {
if n > 0 {
hanio(n - 1, a, c, b)
print("\(a) -> \(b)")
hamoi(n - 1, c, b, a)
}
}
3.函數的參數為函數
1.定義
在Swift中函數是一種類型.這也意味著函數可以作為變量或常量的類型
同理函數也可以作為另一個函數的參數和返回值
2.閉包(匿名函數)
func foo(array: [Int], fn:(Int, Int) -> Int) -> Int
//foo函數中,參數傳入一個數組和一個函數, 返回一個Int。這個函數中的函數就稱為閉包(匿名函數)。
在這個函數中,第二個參數可以傳入的類型有3種
1.使用自定義的函數類型, 新定義一個函數
2.傳入二元運算符:+, -, *, /, %(在Swift中,二元運算符也是一個函數)
3.傳入匿名函數(閉包), 函數沒有名字
//1. 完整的閉包寫法
foo(a, fn:{(a, b) -> Int in return a + b}
//2.省略閉包寫法(在Swift中,一切能省則省, 類型可以省略, 括號也可以省略, 包括參數名也能省略)
//2.1 省略類型
foo(a, fn:(a, b) in a + b )
//2.2 省略括號
foo(a, fn:{a, b in a + b})
//2.3 省略參數名
foo(a, fn: { $0 + $ 1})
3.尾隨閉包
foo(a){ $0 + $ 1}// 這個寫法的條件是, 只有函數參數的最后一個是另一個函數時, 才能使用尾隨閉包寫法
閉包 -就是跟Java和C#中的Lambda函數(Lambda表達式), JavaScript中的匿名函數, C / C++ / Objective - C中的Block起相同作用的東西, 它的存在的意義是實現代碼的解耦合.(實現回調的編程模式)
三.面向對象編程
1.對象, 類和消息
對象:接收消息的單元
1.一切皆為對象
2.對象都有屬性和行為
3.對象都屬于某個類
4.每個對象都是獨一無二的
類:對象的藍圖和模板類是抽象的, 對象是具體的
消息: 對象之間通信的方式, 通過對象互發消息可以構造出復雜的系統
2.訪問修飾符
Public - 公開的
internal - 內部的(默認)
private - 私有的
存儲屬性 -> private 私有化, 不允許隨便修改, 將數據保護起來
計算屬性 -> public 公開, 因為方法是對象接收的消息, 需要調用
方法一般為公開, 對象一般為私有. 如果自定義的類沒有打算在其它項目中使用, 可以不寫訪問修飾符,默認為internal, 表示在本項目中公開對其它項目使用
3.定義和使用類
1.定義一個類, 定義一個類就可以創建出新的類型
2.數據抽象 - 定義類里成員的屬性
3.初始化方法 - 初始化成員變量
4.行為抽象 - 給類寫方法, 完成不同的動作(作用)
5.也可以給類添加一個計算屬性.(通過對存儲屬性作運算得到的屬性)
var name: String // 存儲屬性, 存儲相關的數據的屬性
var sellPrice: Double {
get{ return 0.87 * price} // get表示讀
set{ return sellPrice = newValue}
}// 計算屬性, 通過對存儲屬性做運算得到的屬性
init(name: String, age: Int) {
self.name = name
self.age = age //在同一個類中可以擁有多個init構造方法, 但最終還是會被調用一個指派初始化方法. 相當于在其他init方法中, 再調用一次init方法, 完成初始化
}
4.類擴展
原理: 在一些特殊的情況下, 你在一個類中需要一種特定的功能, 這個類不能幫你實現目的。這個時候你需要利用類擴展(extension), 來現場添加這項功能
//目標是講Point中的成員類型由double -> CGPoint
extension Point { // Point代表需要擴展的類
var cgPoint : CGpoint { // 返回的值類型
get { return CGPointMake(CGPoint(point.x), CGPoint(point.y))} //返回一個CGPoint
}
}
5.運算符的重載
為自定義的類型定義運算符, 寫在類的外邊
在Swift中運算符算是一種函數(方法), 相當于重寫運算符的方法
//實現兩個分數的加法運算, addTo函數實現兩個分數相加的功能
func +(one: Fraction, two: Fraction) -> Fraction {
return one.addTo(two) // 返回一個值為one + two 的分數
}
四. 繼承
1.概念
根據已有的類, 創建新類的過程
提供信息的稱為父類(也叫超類, 基類)
得到繼承信息的稱為子類(也叫派生類, 衍生類)
一般情況下, 子類一般除了得到父類的繼承信息外, 還會增加一些屬于自己特有的東西, 因此子類的能力比父類更強大
繼承的意義主要是減少代碼的復用度, 子類可以直接使用父類的屬性和方法, 還可以增強系統現有的功能
IS-A關系
as!
as?
用法解釋
let person = Person(name: "王鋼蛋", age: 23)
let stu = Student(name: "鋼蛋王", age: 23, lesson: "Swift開發")
let doc = Doctor(name: "王醫生", age: 23, title: "開刀手")
//其中Person是父類, Student, Doctor是子類
//可以將子類型的對象賦值給父類型的變量(父類和子類的關系為IS-A)
let stu2 : Person = Student(name: "鋼蛋王", age: 23, lesson: "IOS網絡課程學習") // stu2對象是一個Person對象
(stu2 as! Student).study // 如果我確定stu2是學生, 可以執行學生獨有的方法, 可以使用as!方法轉換, 將stu2對象類型由Person轉化成student類型
//如果判斷不出來是否為某一種子類的時候, 但是你需要它調用那個類的方法時, 需要用as!來判斷, 返回的是一個Student?類型, 如果是Student類型, 返回true, 否則返回false
if let stu2 as? Student {
print("\(stu2.name)是學生") // 可以通過這種方式, 安全的將父類型的轉化成子類型, 然后才能調用子類型的特有方法
}
2.重寫
父類有的方法子類可以重新實現, 這個過程叫做重寫
重點: 需要在方法前添加 override關鍵子
重寫計算屬性時, 也必須需要加上關子 override
重寫有時也被稱為置換, 覆蓋, 覆寫
五.多態
1.概念
同樣對象類型(父類類型), 接收相同的消息或方法時, 卻做出了不同的事情, 這就叫做多態(polymorphism)
2.實現多態的步驟
1.在子類中重寫父類的方法, 并且需要在各個子類的該方法中實現不同的版本
2.對象造型(意思就是將所有子類對象當次父類對象來用, 來調用重寫的方法)
for book in booksArray {
print("\(book.name)-原價:\(book.price), 售價:\(book.sellPrice)") // 在bookArray中, 分別存的一系列的子類對象, 重寫沒個子類的計算屬性, 導致每個子類sellPrice屬性返回的值都不一樣, 實現多態
}
六.其它知識
1.短除法求x,y最大公約數(利用遞歸)
原理: x和y的最大公約數跟y%x和x最大公約數是一樣的
func gcd(x: Int, _ y: Int) -> Int {
if x > y {
gcd(y, x) // 將大的數放到第一個參數位置上
}
else if y % x != 0 { // 不能整除則不能得到最大公約數,繼續遞歸做判斷
return gcd(y%x, x)
}
else { // 判斷出最大公約數
return x
}
}
2.文檔注釋
方式一. ///通常用來注釋類或者消息
方式二.
/**
吃飯
- parameter food: 食物
- returns: 返回正確true, 錯誤false
*/
func eat(food: String) -> Bool {
}