Swift开篇008->属性

原创 2016年06月01日 11:04:29

PART_A 属性简介

  • 存储属性:存储常量(let)或变量(var),作为实例的一部分. 只能作用于类和结构体

  • 计算属性:计算一个值. 可用于类、结构体、枚举. 必须用 var 声明

  • 类型属性:上述两属性通常与特定类型的实例关联. 该属性可直接作用于类型本身


PART_B 存储属性

  1. 案例

    struct Range {
        var startIndex: Int // 变量存储属性
        let width: Int // 常量存储属性(创建实例时被初始化)
    }
    
    var range = Range(startIndex: 0, width: 5)
    // 区间为 0...5
    range.startIndex = 3
    // 区间为 3...8
  2. 常量结构体的存储属性

    • 当值类型的实例被声明为常量时,其所有属性也成常量

    • 当引用类型的实例被声明为常量后,仍可修改该实例的变量属性

      let rangeFix = Range(startIndex: 3, width: 8)
      rangeFix.startIndex = 1
      // 报错. 因结构体是值类型,而值类型的实例被声明为常量,其属性均成常量
  3. 延迟存储属性:lazy var声明. 第一次被调用时才计算其属性的初始化值

    • 使用场景

      • 当属性的值依赖于在实例的构造过程结束后才会知道具体值的外部因素时

      • 当获得属性的初始值需要复杂或大量计算时

    • 当被 lazy 标记的属性在没有初始化时就同时被多个线程访问,则无法保证该属性只会被初始化一次

      class DataProvider {
          // 导入文件(耗时操作)
          var fileName = "data.txt"
      }
      
      class DataManager {
          lazy var provider = DataProvider()
      
          // 数据管理
          var data = [String]()
      }
      
      let manager = DataManager()
      manager.data.append("Some data")
      manager.data.append("Some more data")
      // DataProvider 实例还没有被创建
      
      
      print(manager.importer.fileName)
      // DataProvider 实例被创建(此时第一次被调用)
  4. 存储属性和实例变量

    • Swift 中的属性没有对应的实例变量,属性的后端存储也无法直接访问

PART_C 计算属性(-案例值得琢磨-)

  1. 不直接存储值,提供 gettersetter 来间接获取和设置值

    // 定义中心坐标
    struct Point {
        var x = 0.0, y = 0.0
    }
    
    // 定义宽高
    struct Size {
        var width = 0.0, height = 0.0
    }
    
    // 定义矩形
    struct Rect {
    
        var origin = Point()
        var size = Size()
    
        var center: Point {
            // getter:返回 Point 实例(中心)
            get {
                let centerX = origin.x + (size.width / 2)
                let centerY = origin.y + (size.height / 2)
                return Point(x: centerX, y: centerY)
            }
    
            // setter:设置 Point 中心坐标
            set(newCenter) {
                origin.x = newCenter.x - (size.width / 2)
                origin.y = newCenter.y - (size.height / 2)
            }
        }
    }
    
    var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))
    
    let squareCenter = square.center
    // 中心坐标 (5, 5)
    
    square.center = Point(x: 15.0, y: 15.0)
    
    print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
    // 输出 "square.origin is now at (10.0, 10.0)”
  2. 便捷 setter 声明

    • 若计算属性的 setter 没有定义新值的参数名,则可使用默认名称 newValue

      // 上述代码的 setter 可简写
      set {
          origin.x = newCenter.x - (size.width / 2)
          origin.y = newCenter.y - (size.height / 2)
      }
  3. 只读计算属性:只有 getter 没有 setter 的计算属性,总是返回一个值

    struct Cuboid {
        var width = 0.0, height = 0.0, depth = 0.0
    
        // 只读计算属性
        var volume: Double {
            return width * height * depth
        }
    }
    
    let rect1 = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
    print("the volume of rect1 is \(rect1.volume)")

PART_D 属性观察器

  • 可为除延迟存储属性外的其他存储属性添加

  • 可通过重写属性的方式为继承的属性(存储属性、计算属性)添加

  • 父类的属性在子类构造器中被赋值时,其在父类的观察器会被调用

  • 可为属性添加如下一个或全部观察器

    • willSet:新值被设置前调用

    • didSet:新值被设置后调用

      class StepCounter {
          var totalSetps: Int = 0 {
              // newTotalSteps:新值(默认 newValue)
              willSet(newTotalSteps) {
                  print(newTotalSteps)
              } didSet {
                  // oldValue:旧值 
                  if totalSetps > oldValue {
                      print(totalSetps - oldValue)
                  }
              }
          }
      }
      
      let stepCounter = StepCounter()
      stepCounter.totalSetps = 50
      // 50
      // 50
      
      stepCounter.totalSetps = 90
      // 90
      // 40
      
      stepCounter.totalSetps = 80
      // 80
  • 若一个属性的 didSet 观察器里赋值,该值会替代之前设置的值


PATR_E 全局变量和局部变量

  1. 定义

    • 全局变量:在函数、方法、闭包或任何类型之外定义的变量

    • 局部变量:在函数、方法或闭包内部定义的变量

  2. 注意

    • 全局的常量或变量都是延迟计算的(省略 lazy 修饰符)

    • 局部的常量或变量从不延迟计算

  3. 计算属性和属性观察器所描述的功能可用于全局变量和局部变量


PART_F 类型属性(static):定义某个类型所有实例共享的数据

  • 实例属性属特定类型的实例,每创建一个实例,实例都拥有属于自己的一套属性值,实例间的属性相互独立

  • 必须给存储型类型属性指定默认值(无构造器,无法初始化时赋值)

  • 存储型类型属性是延迟初始化的(省略 lazy). 即使它们被多个线程同时访问,系统也保证只会对其进行一次初始化


  1. 语法

    struct SomeStructure {
        // 存储型类型属性
        static var storedTypeProperty = "Some value."
        // 计算型类型属性(本例所用是只读的)
        static var computedTypeProperty: Int {
            return 5
        }
    }
    enum SomeEnumeration {
        static var storedTypeProperty = "Some value."
        static var computedTypeProperty: Int {
            return 6
        }
    }
    class SomeClass {
        static var storedTypeProperty = "Some value."
        static var computedTypeProperty: Int {
            return 7
        }
    
        // 为类定义计算型类型属性时,改用 class 支持子类对父类的实现进行重写
        class var overrideableComputedTypeProperty: Int {
            return 8
        }
    }
  2. 获取和设置类型属性的值

    • 和实例属性一样通过 .,但类型属性是通过类型本身来访问(是不是很像JAVA的静态类)

      SomeStructure.storedTypeProperty = "Another value."

  3. 案例:两个喇叭的音量

    struct AudioChannel {
    
        // 常量存储类型属性:音量上限
        static let thresholdLevel = 10
    
        // 变量存储类型属性:输入音量
        static var maxInputLevelForAllChannels = 0
    
        // 存储型实例属性:当前声道音量
        var currentLevel: Int = 0 {
            // 属性观察器
            didSet {
                if currentLevel > AudioChannel.thresholdLevel {
                    // 将当前音量限制在音量上限内
                    currentLevel = AudioChannel.thresholdLevel
                }
                if currentLevel > AudioChannel.maxInputLevelForAllChannels {
                    // 存储音量上限
                    AudioChannel.maxInputLevelForAllChannels = currentLevel
                }
            }
        }
    }
    
    var leftChannel = AudioChannel()
    var rightChannel = AudioChannel()
    
    leftChannel.currentLevel = 7 // 左声道音量为 7
    rightChannel.currentLevel = 11 // 右声道音量为 10(控制在音量上限内)

以上。如有错误和疑问,欢迎指正提出。 catface.wyh@gmail.com

版权声明:本文为博主原创文章,如需转载请声明作者信息,谢谢。

小白张的博客开篇

2016年转眼之间已经过去一半,而我毕业也已经整整一年了。在过去一年里,个人成长可以说是非常缓慢的,JavaEE开发算是刚刚入门,其实就是一个名副其实的小白。对于各种框架技术都是一知半解,只是能用但是...
  • GallenZhang
  • GallenZhang
  • 2016年07月17日 11:19
  • 945

个人学习笔记开篇

大学毕业到现在已经工作了半年时间了,虽然一直在为公司的编辑器一刻不停的做功能,不过真正学习到的知识貌似没多少,倒发现了自己一身的缺点。知识体系了解的不够深刻,基础不够扎实,做事比较粗心。为了能在之后的...
  • jhgameboy
  • jhgameboy
  • 2014年01月30日 00:44
  • 1004

Android系统-开篇

一、Android概述Android系统非常庞大,底层是采用Linux作为基底,上层采用带有虚拟机的Java层,通过通过JNI技术,将上下打通,融为一体。下图是Google提供的一张经典的4层架构图,...
  • Gityuan
  • Gityuan
  • 2016年03月06日 21:07
  • 1529

swift自学笔记(五)(重写属性、final)

//************重写父类的存储属性***********// class car {     var name:String = "b" } clas...
  • iOS_Pop
  • iOS_Pop
  • 2016年01月27日 11:05
  • 1139

Swift类属性定义

Swift中类的属性有多种 存储属性:存储实例的常量和变量 计算属性:通过某种方式计算出来的属性 类属性:与整个类自身相关的属性一、存储属性存储属性是最简单的属性,它作为类实例的一部分,用于存储...
  • github_26672553
  • github_26672553
  • 2016年09月16日 20:48
  • 2453

Swift 属性(九)

属性 (Properties) 1.存储属性 存储在类或结构体的实例中的一个变量或常量,可以在定义的时候赋值,也可以在构造过程时候赋值 // length定义为常量,在创建实例的时候赋值...
  • huangchentao
  • huangchentao
  • 2014年06月20日 16:23
  • 4159

swift 将闭包声明属性使用

声明 typealias blockLogin1=(obj_bolck:String)->Void var blockLogin = blockLogin1?() 调用 se...
  • hyc_springBrother
  • hyc_springBrother
  • 2016年03月29日 15:38
  • 2936

swift 开篇

Swift是苹果昨天推出一种新的变成语音
  • haifengzhilian
  • haifengzhilian
  • 2014年06月03日 11:24
  • 1482

【iOS】Swift类与结构、存储属性、计算属性、函数与方法、附属脚本等

写了12个Person来复习,不过完成同样的代码需要敲键盘的次数相比OC确实少了很多,这很多应该归功于Swift中不写分号,以及少了OC中的中括号。 一、类与结构体 两者在Swift中差不了多少了 ...
  • xn4545945
  • xn4545945
  • 2014年09月16日 05:08
  • 11208

9.7 Swift属性观察器

/**          属性观察器          观察属性的变化,是指属性被修改时可以调用我们事先写好的代码去额外执行一些操作。          类似于OC中的KVO ...
  • sinat_20037505
  • sinat_20037505
  • 2016年12月19日 06:21
  • 330
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Swift开篇008->属性
举报原因:
原因补充:

(最多只允许输入30个字)