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

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

相关文章推荐

008--swift基础语法(数组)

数组的定义 //MARK: -数组的定义 func demo1() { //OC使用[]定义数组,Swift一样,但是没有`@` //自动推导的结果是[St...

Android属性动画实战教程开篇

本系列博客会分俩篇 本篇博客主要是会介绍属性动画代码使用和xml中使用 关于View动画和属性动画的区别不做过多的介绍,当然涉及到的地方会简单的提一下。好了废话不多说,直接上内容 首先介绍代码中使用属...

Swift 属性学习笔记

Swift 属性的学习笔记、 存储属性、计算属性

swift - 类和结构体(之属性)

值类型和引用类型中可以通过外部访问的成员(除了方法外)都叫做属性。 swift中到底存在多少种属性? 1.存储属性 类和结构体的成员变量或者成员常量都属于存储属性。 struct FixedLengt...

iOS swift 字符属性NSAttributedString描述

/*  字符属性    字符属性可以应用于 attributed string 的文本中。    NSString *const NSFontAttributeName;...

Swift学习记录 -- 13.类的构造方法及属性监听

类的构造方法原理和OC差不多 , 只是属性手动赋值时 , 有些麻烦 , 也有些难以理解 , 不过幸好有KVC , 解决了大部分问题 . 至于属性观察 , 调用的方法想必也不陌生 , 不错 , 正是OC...

《 Swift UITabBarController 的使用和自定义TabBar,和部分属性和代理的使用》

/*      《 Swift  UITabBarController 的使用和自定义TabBar,和部分属性和代理的使用》 */ /*     标签栏控制器是当前市场App...

《从零开始学Swift》学习笔记(Day 38)——构造函数与存储属性初始化

构造函数的主要作用是初始化实例,其中包括:初始化存储属性和其它的初始化。在Rectangle类或结构体中,如果在构造函数中初始化存储属性width和height后,那么在定义他们时就不需要初始化了。 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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