學習不像愛情潦牛。愛情你一認真就輸了思恐。學習你一認真就贏了笼平。
A plant may produce new flowers; man is young but once.
(花有重開日逸贾,人無再少年)
OOP: Object Oriented Programming 面向?qū)ο蟮某绦蛟O計
Swift語言中陨仅,不僅類具有面向?qū)ο蟮奶卣鳎?strong>結構體與枚舉都具有面向?qū)ο蟮奶卣鳌5?strong>類是引用類型铝侵,結構體與枚舉是值類型(作為參數(shù)需要修改內(nèi)容時有區(qū)別灼伤,類直接傳對象 其他傳地址&)。
類的“實例”一般稱為“對象”咪鲜,但是狐赡,枚舉與結構體的“實例”不能稱之為“對象”,因為它們不是真正的面向?qū)ο箢愋?/strong>疟丙。只是包含了面向?qū)ο蟮奶攸c颖侄。
1、枚舉 - 值類型
-
枚舉 = 成員值 + 相關值 (成員值 后 可加 原始值)
-
成員值
-
定義 - 枚舉的成員值 默認情況下 不是整數(shù)類型0,1,...
enum WeekDays { case Monday case Tuesday case Wednesday case Thursday case Friday // 注意:如果枚舉成員類型不同這樣寫case c(Character) } // 簡易寫法 enum weekDays: Int{ case Monday, Tuesday, Wednesday, Thursday, Firday }
-
賦值
var day = weekDays.Monday // 枚舉類型名稱.成員值 day = .Monday // .成員值 能這么用的前提:必須有上下文享郊,Swift能判斷出類型 switch day { case .Monday: print("Monday") case .Tuesday: print("Tuesday") case .Wednesday: print("Wednesday") case .Thursday: print("Thursday") case .Firday: print("Firday") // default: // print("default") /** default分支在枚舉中可以省略览祖,使用其他類型是不允許省略的。 只要枚舉中case列舉完畢所有可能值炊琉, default可省略展蒂,不省略有warning又活。 如果 存在default同時不存在warning,那么可以把case .Firday 分支去掉 (其實去掉任何一個分支都可以锰悼,只要滿足所有可能性全包括了即可)*/ }
-
-
原始值(raw value)
-
可以是字符柳骄、字符串、整數(shù)箕般、浮點數(shù)等
// 1耐薯、加入數(shù)據(jù)類型Int 2、加入默認值0,1,2,... enum weekDays: Int{ // 之后自動加1丝里。也可以case Monday = 0 case Tuesday = 1...分開寫,也可只給第一個成員賦值曲初,后面成員值會依次+1 case Monday = 0, Tuesday, Wednesday, Thursday, Firday } let friday = weekDays.Firday.rawValue // 4 成員值->原始值 let thursday = weekDays(rawValue: 3) // Thursday 原始值->成員值,是 調(diào)用枚舉的 構造函數(shù) 初始化 枚舉的實例丙者。
-
-
相關值
/** 枚舉的相關值 枚舉中成員值 相關值 一般首字母大寫复斥,就像OC中的枚舉前面也是大寫(前綴是大寫的) */ enum Figure{ case Rectangle(Int, Int) case Circle(Int) } func printFigure(figure: Figure){ switch figure { /** 自帶值的提取P得健目锭! 如果某個相關值元組中字段類型一致,需要全部提取纷捞, 可以將字段前面的let或者var移到相關值前面痢虹。 case let .Rectangle(width, height): case let .Circle(radius): 字段是一個的也可以,但是沒有必要 */ case .Rectangle(let width, let height): print("矩形的寬\(width)高\(height)") case .Circle(let radius): print("圓的半徑\(radius)") } } printFigure(figure: Figure.Rectangle(2, 1)) printFigure(figure: Figure.Circle(2)) // 打印 矩形的寬2高1 圓的半徑2
2主儡、結構體 - 值類型
Swift重視結構體奖唯,把結構體作為實現(xiàn)面向?qū)ο蟮闹匾侄巍2粌H可以定義成員變量也就是屬性糜值,還可以定義成員方法丰捷。可以看作是一種輕量級的類寂汇。(而其他語言中的結構體 只能定義一組相關的成員變量)
-
結構體的定義 : struct + 結構體名稱{ 成員變量 }
// 部門(下文要用到此結構體實例化) - 部門與員工是1 : n的關系(1 對 多的關系) struct Department{ var no: Int = 0 var name: String = "" }
-
結構體的實例化--如果要給結構體的成員變量賦值病往,用var不用let。而類一般用let
var dept1 = Department() // 有屬性賦值必須是var dept1.no = 10 dept1.name = "Sales"
3骄瓣、類 - 引用類型
-
類的定義
// 員工類(下文要用此類實例化) - 員工與部門是n : 1的關系 class Employee{ var no: Int = 0 var name: String = "" var job: String? var salory: Double = 0.0 var dept: Department? // 結構體類型所在部門屬性 }
-
類的實例化--類一般聲明為let常量停巷,由于類是引用數(shù)據(jù)類型,聲明為let常量只是說明不能修改引用(比如下面的emp1)榕栏,但是可以通過內(nèi)存地址拿到對應的對象畔勤,修改對象內(nèi)部的屬性
let emp1 = Employee() emp1.no = 1000 emp1.name = "Martin" emp1.job = "Salesman" emp1.salory = 1250
4、 值類型與引用類型
-
類是引用類型扒磁,其他類型全是值類型G炀尽!(再記一遍妨托,重要)
引用類型 與 值類型 修改內(nèi)容舉例:// 創(chuàng)建實例 var dept = Department() // var dept.no = 10 dept.name = "Sales" let emp = Employee() emp.no = 1000 emp.name = "Martin" emp.job = "Salesman" emp.salory = 1250 ================= 值類型分割線 ================ #warning 值類型 /** 不加inout嚷硫,傳入dept检访,編譯失敗,修改不成功仔掸,說明了結構體是值類型, 引用類型不用加inout 傳入引用對象即可修改成功 */ func updateDept(dept: inout Department){ dept.name = "Research" } print("Deparment更新前\(dept.name)") // "Sales" updateDept(dept: &dept) print("Deparment更新后\(dept.name)") // "Research" ================= 引用類型分割線 ================ #warning 引用類型 func updateEmp(emp: Employee){ emp.job = "Clerk" } print("Employment更新前\(emp.job!)") // "Salesman" job是可選類型 需要解包 updateEmp(emp: emp) print("Employment更新后\(emp.job!)") // "Clerk"
5医清、引用類型的比較
-
對于引用類型的實例比較起暮,比如類的實例比較 只能用=== 與 !==
-
結構體與類實例化
var dept1 = Department() // var 結構體 dept1.no = 10 dept1.name = "Sales" var dept2 = Department() // var 結構體 dept2.no = 10 dept2.name = "Sales" let emp1 = Employee() // 對象 emp1.no = 1000 emp1.name = "Martin" emp1.job = "Salesman" emp1.salory = 1250 let emp2 = Employee() // 對象 emp2.no = 1000 emp2.name = "Martin" emp2.job = "Salesman" emp2.salory = 1250
-
類實例比較 & 結構體屬性的比較
// 比較是否實例相等 if emp1 !== emp2{ // false : 不同的對象 print("emp1 !== emp2") } if emp1 === emp1 { // true : 同一個對象 print("emp1 === emp1") } if dept1.no == dept2.no { // true : 值相等 print("dept1.no == dept2.no") }
-
結構體的實例比較 - 編譯失敗
if dept1 == dept2 { // 編譯失敗:對于枚舉 與結構體 直接比較編譯失敗会烙,需要運算符重載 print("dept1 == dept2") }else{ print("dept1 != dept2") }
-
運算符重載 - 編譯成功
// 運算符重載:每對屬性分別比較负懦。調(diào)用d1 == d2固定調(diào)用寫法 func ==(d1: Department, d2: Department) -> Bool{ return d1.no == d2.no && d1.name == d2.name } func !=(d1: Department, d2: Department) -> Bool{ return d1.no != d2.no || d1.name != d2.name } 打印結果: dept1 == dept2
注明: 判斷中dept1 == dept2語句調(diào)用該運算符的重載函數(shù),對于有多個判斷是否相等的重載函數(shù)柏腻,應該調(diào)用哪個重載函數(shù)由重載函數(shù)的參數(shù)類型(如:Department)決定纸厉。
-
6、 類型嵌套
關于類型嵌套五嫂,它會使程序結構變得不清晰颗品,可讀性差。
優(yōu)點:支持訪問外部類的成員沃缘,成員包括:方法躯枢,屬性,枚舉槐臀,結構體等嵌套類型
-
訪問:對象名.屬性名锄蹂,對象名.枚舉實例,對象名.結構體實例水慨,類名.枚舉名.枚舉成員值(.rawValue)得糜,
不能對象名.枚舉名,對象名.結構體名// 類型嵌套的使用 class Employee{ var no: Int = 0 var name: String = "" var job: String? var salary: Double = 0 var dept: Department = Department() var day: WeekDays = WeekDays.Friday struct Department { // 里一層 var no: Int = 10 var name: String = "SALES" } enum WeekDays { // 里一層 case Monday case Tuesday case Wednesday case Thursday case Friday struct Day { // 里二層 static var message: String = "Today is..." } } } ============= 實例化分割線 ========== var emp = Employee() print(emp.dept.name) print(emp.day) // 對象emp不能調(diào)用結構體 枚舉等名 let friday = Employee.WeekDays.Friday if emp.day == friday { print("相等") } print(Employee.WeekDays.Day.message) // 一層嵌套一層晰洒。類名稱只能直接調(diào)用枚舉名稱 結構體名稱 //print(Employee.WeekDays.Day) 編譯失敗朝抖, 括號內(nèi)必須是字符串,枚舉沒有成員默認值
7欢顷、可選鏈
可選鏈是在類型嵌套中常用的槽棍。比如外部類Employee有個屬性不確定有沒有值的存在(eg: var dept: Department?),這個屬性是個嵌套類類型(成員有var comp: Company?)抬驴,Company又是一個嵌套類類型(成員有var name: String = "張三")炼七。
-
如果要訪問name,會這么做:
let emp = Employee() print(emp.dept!.comp!.name) // 顯式拆包 // 但是顯式拆包有個弊端布持,如果可選鏈中某個環(huán)節(jié)為nil豌拙,將會導致代碼運行錯誤 // fatal error: unexpectedly found nil while unwrapping an Optional value // (之前基本數(shù)據(jù)類型賦值對于nil是用可選綁定解決的) print(emp.dept?.comp?.name) // 可選鏈 // 如果某個環(huán)節(jié)為nil,不會拋出異常题暖,會把nil返回給引用者
注意:在可選鏈中按傅,最后的字段不能再加問號捉超,會報錯:error: '?' must be followed by a call, member lookup, or subscript