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)換