Swift基础入门之枚举、结构体和类

352 阅读4分钟

enum

  • 类似于OC的结构

    • 成员值在创建时不会被赋予一个默认整型值,类型就是枚举名称
    • 可以像类和结构体一样增加属性和方法
  • 省略枚举名的(.)语法

    • 当变量类型可以推断出特定类型时,可以省略枚举名
    // 枚举的定义如下
    enum DaysOfWeak {
        case Sunday  // case 关键字表示新的成员值将被定义
        case Monday
        case Tuesday
        case Thursday
        case Friday
        case Saturday
    }
    
    var weekDay: DaysOfWeak = .Friday
    
  • 原始值枚举

    • 枚举成员的数据类型相同,可以是字符串、整型、浮点型
    • 原始值枚举的值定义后不可改
      // Int类型的枚举
      enum DaysOfWeak: Int {
          case Sunday  // case 关键字表示新的成员值将被定义
          case Monday
          case Tuesday
          case Thursday
          case Friday
          case Saturday
      }
      
      enum DaysOfWeak: Int {
      // 可以以逗号隔开,定义成一行
      case Sunday, Monday, Tuesday, Thursday, Friday, Saturday
      }
      
      // 在原始值为整数的枚举时,不需要显式的为每一个成员赋值,Swift会自动为你赋值。
      var weekDay: DaysOfWeak = .Friday
      print(weekDay.rawValue)  //rawValue 代表将枚举值转换为原始值,返回的是可选值,原始值不一定存在
      
  • 相关值枚举

    • 枚举对应的原始值是一个变量
      enum DaysOfWeak {
        case Name(Int)
        case EnglishName(String)
      }
      
      var dayName = DaysOfWeak.Name(0)
      var dayEnglishName = DaysOfWeak.EnglishName("Sunday")
      
      switch dayEnglishName {
      case .Name(let day):
          print("\(day)")
      case .EnglishName(let dayName):
          print(dayName)
      }
      

struct

  • 可以为结构体创建属性和方法

  • 结构体是通过被复制的方式在代码中传递,它的值是不可以被修改的

    struct MarkStruct {
        var mark1 = 100
        var mark2 = 89
        init(mark1: Int, mark2: Int) {
            self.mark1 = mark1
            self.mark2 = mark2
        }
    }
    
    var A = MarkStruct(mark1: 100, mark2: 200)
    A.mark1 = 200
    
    var B = A   // 值传递
    B.mark1 = 100
    
    print(A.mark1)  // 输出200
    print(B.mark1)  // 输出100
    
  • 不可以继承,提供默认初始化方法

  • struct的方法中修改属性的时候需要使用mutating

    struct MarkStruct {
        var mark1 = 100
        var mark2 = 89
        init(mark1: Int, mark2: Int) {
            self.mark1 = mark1
            self.mark2 = mark2
        }
        // 在struct修改属性的时候需要使用mutating
        mutating func modifyProperty(p: Int) {
            self.mark2 += p
        }
    }
    
  • let声明的struct实例,不能改变对应属性的值

    let p1 = MarkStruct(mark1: 100, mark2: 200)
    
    p1.mark2 = 200 // 报错
    
  • 优势:

    • struct不需要考虑内存泄漏和多线程读写问题
    • struct存储在栈中,class存储在堆中,struct更快

class

  • class是引用类型,当值传递的时候,它是传递对已有实例的引用
    class MarkStruct {
        var mark1 = 100
        var mark2 = 89
        init(mark1: Int, mark2: Int) {
            self.mark1 = mark1
            self.mark2 = mark2
        }
        func modifyProperty(p: Int) {
            self.mark2 += p
        }
    }
    
    let p = MarkStruct(mark1: 1, mark2: 2)
    p.mark1 = 100;
    
    let p0 = MarkStruct(mark1: 1, mark2: 2)
    p0.mark1 = 150;
    
    let p1 = p
    p1.mark1 = 200  // p和p1的mark1都是200
    
    p1 = p0  // 报错
    
  • ===
    • 两个变量或者常量引用同一个instance
  • !==
    • 不恒等运算符,两个变量或者常量不引用同一个instance
  • ==
    • 两个变量或者常量的值是否相当,不一定引用同一个instance

    • 如果想让自定义的class支持==操作符,可以使该类遵守Equatable

      class Animal {
          var name: String?
          var weight = 0.0
      }
      
      extension Animal: Equatable {
          static func == (lhs: Animal, rhs: Animal) -> Bool {
              return lhs.name == rhs.name && lhs.weight == rhs.weight
          }
      }
      
      let blackCat = Animal()
      blackCat.name = "catName"
      blackCat.weight = 10
      
      let tmpCat = Animal()
      tmpCat.name = blackCat.name
      tmpCat.weight = blackCat.weight
      
      if blackCat !== tmpCat {
          print("tmp !==")
      }
      if blackCat == tmpCat {
          print("tmp ==")
      }
      

属性

  • 存储属性
    • 类或者结构体中定义的常量或者变量
    • lazy延迟加载属性
      • 只支持变量,不支持常量
      class LabelUI: UIView {
        lazy var label: UILabel = {
            let temp = UILabel()
            temp.text = "test"
            temp.font = UIFont.boldSystemFont(ofSize: 10)
            return temp
        }()
      }	
      
  • 计算属性
    • 计算属性,提供一个getter方法来获取值,提供一个可选的setter来设置值
    class LabelUI: UIView {
    
      // 计算属性,
      var updateView: String {
          get {
              self.label.text!
          }
          set (name) { // 默认名称newValue
              self.label.text = name
          }
      }
    
      // 只要get方法的只读计算属性,可以省略`get`和`{}`
      var width: Float {
          return 10
      }
    
      lazy var label: UILabel = {
          let temp = UILabel()
          temp.text = "test"
          temp.font = UIFont.boldSystemFont(ofSize: 10)
          return temp
      }()
    }
    
  • 属性观察器
    • 监控和响应属性值的变化
    • willSetdidSet在属性初始化过程中不会被调用
      var counter: Int = 0 {
          willSet {
              print(newValue)
          }
          didSet {
              print(oldValue)
          }
      }
      
  • 类型属性
    • static定义值类型的类型属性
    • class定义引用类型的类型属性
      struct S {
          static var name = ""
      }
      
      enum N {
          static var name = ""
      }
      
      class C {
          class var name : String {
              return ""
          }
      }
      
      S.name = "name"
      print(S.name)
      
      N.name = "test"
      print(N.name)
      
      print(C.name)
      

继承

  • 基类(base Class)

  • 子类

    • 在一个已有类的基础上创建一个新的类。
  • Overriding

    • 在属性重写中提供了setter,那么也一定要提供getter
    • 重写父类的方法、属性、下标脚本
    class BaseClass {
        var radius = 12
    
        var area: String {
            return "半径:\(radius)"
        }
    
        func show() {
            print("baseClass")
        }
    }
    
    class SubClass: BaseClass {
        override var radius: Int {
            // 可以为继承来的属性添加属性观察器,这样,属性变化时,可以检测到
            didSet {
                print("radius")
            }
        }
        override var area: String {
            // super.area可以返回继承来的值
            return super.area + " sub"
        }
    
        override func show() {
            print("subClass")
        }
    }
    
    let sub = SubClass()
    sub.show()  // 输出subClass
    sub.radius = 10
    sub.area    // 半径:12 sub
    
  • final

    • final修饰类,类不能被继承
    • final修饰属性方法,则该方法不支持重写

引用