Swift(四 面向对象OOP特征)

作者: DSA碼侬 | 来源:发表于2017-08-16 13:52 被阅读35次

学习不像爱情。爱情你一认真就输了。学习你一认真就赢了。
A plant may produce new flowers; man is young but once.
(花有重开日,人无再少年)

  • OOP: Object Oriented Programming 面向对象的程序设计

  • Swift语言中,不仅具有面向对象的特征,结构体枚举都具有面向对象的特征。但是类是引用类型,结构体与枚举是值类型(作为参数需要修改内容时有区别,类直接传对象 其他传地址&)。

  • 的“实例”一般称为“对象”,但是,枚举结构体的“实例”不能称之为“对象”,因为它们不是真正的面向对象类型。只是包含了面向对象的特点。

1、枚举 - 值类型

  • 枚举 = 成员值 + 相关值 (成员值 后 可加 原始值)
  • 成员值

    • 定义 - 枚举的成员值 默认情况下 不是整数类型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)

    • 可以是字符、字符串、整数、浮点数等

       // 1、加入数据类型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 原始值->成员值,是 调用枚举的 构造函数 初始化 枚举的实例。
      
  • 相关值

            /** 
            枚举的相关值
            枚举中成员值 相关值 一般首字母大写,就像OC中的枚举前面也是大写(前缀是大写的)
            */
        enum Figure{
             case Rectangle(Int, Int)  
             case Circle(Int)
          }
    
    
        func printFigure(figure: Figure){
    
         switch figure {
             /**
               自带值的提取!!
               如果某个相关值元组中字段类型一致,需要全部提取,
               可以将字段前面的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重视结构体,把结构体作为实现面向对象的重要手段。不仅可以定义成员变量也就是属性,还可以定义成员方法。可以看作是一种轻量级的类。(而其他语言中的结构体 只能定义一组相关的成员变量)

  • 结构体的定义 : 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常量,由于类是引用数据类型,声明为let常量只是说明不能修改引用(比如下面的emp1),但是可以通过内存地址拿到对应的对象,修改对象内部的属性

    let emp1 = Employee()
    emp1.no = 1000
    emp1.name = "Martin"
    emp1.job = "Salesman"
    emp1.salory = 1250
    

4、 值类型与引用类型

  • 类是引用类型,其他类型全是值类型!!(再记一遍,重要)
    引用类型 与 值类型 修改内容举例:

     // 创建实例
     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")
        }
      
    • 运算符重载 - 编译成功

      // 运算符重载:每对属性分别比较。调用d1 == d2固定调用写法
      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语句调用该运算符的重载函数,对于有多个判断是否相等的重载函数,应该调用哪个重载函数由重载函数的参数类型(如:Department)决定。

6、 类型嵌套

  • 关于类型嵌套,它会使程序结构变得不清晰,可读性差。

  • 优点:支持访问外部类的成员,成员包括:方法,属性,枚举,结构体等嵌套类型

  • 访问:对象名.属性名,对象名.枚举实例,对象名.结构体实例,类名.枚举名.枚举成员值(.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不能调用结构体  枚举等名
    
       let friday = Employee.WeekDays.Friday
       if emp.day == friday {
             print("相等")
        }
       print(Employee.WeekDays.Day.message) // 一层嵌套一层。类名称只能直接调用枚举名称 结构体名称
       //print(Employee.WeekDays.Day)   编译失败, 括号内必须是字符串,枚举没有成员默认值
    

7、可选链

  • 可选链是在类型嵌套中常用的。比如外部类Employee有个属性不确定有没有值的存在(eg: var dept: Department?),这个属性是个嵌套类类型(成员有var comp: Company?),Company又是一个嵌套类类型(成员有var name: String = "张三")。

  • 如果要访问name,会这么做:

       let emp = Employee()
       print(emp.dept!.comp!.name)   // 显式拆包
    // 但是显式拆包有个弊端,如果可选链中某个环节为nil,将会导致代码运行错误
    // fatal error: unexpectedly found nil while unwrapping an Optional value
    // (之前基本数据类型赋值对于nil是用可选绑定解决的)
      
       print(emp.dept?.comp?.name)   // 可选链  
     // 如果某个环节为nil,不会抛出异常,会把nil返回给引用者
    

注意:在可选链中,最后的字段不能再加问号,会报错:error: '?' must be followed by a call, member lookup, or subscript

相关文章

  • Swift(四 面向对象OOP特征)

    学习不像爱情。爱情你一认真就输了。学习你一认真就赢了。A plant may produce new flower...

  • 关于oop和aop

    oop oop(Object Oriented Programming)面向对象编程, oop的设计特征:封装, ...

  • 面向对象编程

    1、Object Oriented Programming简称OOP 2、面向对象的特征 (1)抽象:面向对象编程...

  • OC中自定义初始化 与 方法分类

    面向对象的三大特征, 封装, 继承与多态!面向对象编程OOP(Object Oriented Programmin...

  • 对象_原型

    问题1: OOP 指什么?有哪些特性 OOP指的是面向对象编程。就是将事物抽象成对象。面向对象的三个基本特征是:封...

  • Python--类和对象学习

    一、面向对象编程概述 1、面向对象编程(OOP) 面向对象:以具体的事物(对象)为单位,考虑它的属性(特征)及动作...

  • 学习UML1--OOP与类关系

    学习UML首先要了解面向对象的主要特征以及对象之间的关系。 OOP(面向对象)主要特征:抽象:强调实体的本质、内在...

  • 面向对象编程

    1. 面向过程、面向对象 OOP、函数式编程 2. 面向对象三大基本特征:封装、继承、多态 封装: 隐藏内部的变量...

  • 面向对象

    面向对象 - OOP(Object Oriented Programming) 面向对象的四大支柱:抽象: 类是...

  • Java面试总结

    1.什么是OOP、AOP OOP即面向对象编程OOP三大特征:封装、继承、多态OOP五大原则:单一职责原则 (Si...

网友评论

    本文标题:Swift(四 面向对象OOP特征)

    本文链接:https://www.haomeiwen.com/subject/xywurxtx.html