Swift(四 面向?qū)ο驩OP特征)

學習不像愛情潦牛。愛情你一認真就輸了思恐。學習你一認真就贏了笼平。
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

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市唯绍,隨后出現(xiàn)的幾起案子拼岳,更是在濱河造成了極大的恐慌,老刑警劉巖况芒,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惜纸,死亡現(xiàn)場離奇詭異,居然都是意外死亡绝骚,警方通過查閱死者的電腦和手機耐版,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來压汪,“玉大人粪牲,你說我怎么就攤上這事≈蛊剩” “怎么了腺阳?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長滴须。 經(jīng)常有香客問我舌狗,道長,這世上最難降的妖魔是什么扔水? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任痛侍,我火速辦了婚禮,結果婚禮上魔市,老公的妹妹穿的比我還像新娘主届。我一直安慰自己,他們只是感情好待德,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布君丁。 她就那樣靜靜地躺著,像睡著了一般将宪。 火紅的嫁衣襯著肌膚如雪绘闷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天较坛,我揣著相機與錄音印蔗,去河邊找鬼。 笑死丑勤,一個胖子當著我的面吹牛华嘹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播法竞,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼耙厚,長吁一口氣:“原來是場噩夢啊……” “哼强挫!你這毒婦竟也來了?” 一聲冷哼從身側響起薛躬,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤俯渤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后型宝,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體稠诲,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年诡曙,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片略水。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡价卤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出渊涝,到底是詐尸還是另有隱情慎璧,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布跨释,位于F島的核電站胸私,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏鳖谈。R本人自食惡果不足惜岁疼,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缆娃。 院中可真熱鬧捷绒,春花似錦、人聲如沸贯要。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽崇渗。三九已至字逗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宅广,已是汗流浹背葫掉。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留乘碑,地道東北人挖息。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像兽肤,于是被迫代替她去往敵國和親套腹。 傳聞我的和親對象是個殘疾皇子绪抛,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349

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