//属性

import UIKit

//属性(Properties)详解

/*

存储属性(Stored Properties):类、结构体中,不能在枚举中

计算属性(Computed Properties):类、结构体、枚举中,只能定义为变量

1.计算属性不直接存储值,而是提供一个 get{...return...} 和一个可选的 set(newValue){...},来间接获取和设置其他属性或变量的值。

2.必须定义为变量var,包括只读计算属性,因为它们的值不是固定的

延迟属性:当第一次被调用的时候才会计算其初始值的属性,用lazy来标示

1.必须将延迟存储属性声明成变量(var),因为属性的初始值可能在实例构造完成之后才会得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。

2.使用情况:当属性的值依赖于在实例的构造过程结束后才会知道具体值的外部因素时,或者当获得属性的初始值需要复杂或大量计算时,可以只在需要的时候计算它

属性观察器(Property Observers):监控和响应属性值的变化,每次属性被设置值的时候都会调用属性观察器,甚至新值和当前值相同的时候也不例外。可以为除了延迟存储属性之外的其他存储属性添加属性观察器,也可以通过重写属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器

1.willSet在新的值被设置之前调用,将新的属性值作为常量参数传入,可以为该参数命名或者使用默认参数名newValue

2.didSet在新的值被设置之后立即调用,将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名oldValue

3.父类的属性在子类的构造器中被赋值时,它在父类中的willSet和didSet观察器会被调用

全局变量和局部变量(Global and Local Variables):

1.全局变量是在函数、方法、闭包或任何类型之外定义的变量。局部变量是在函数、方法或闭包内部定义的变量。

2.在全局或局部范围都可以定义计算型变量和为存储型变量定义观察器。计算型变量跟计算属性一样,返回一个计算结果而不是存储值,声明格式也完全一样。

3.全局的常量或变量都是延迟计算的,跟延迟存储属性相似,不同的地方在于,全局的常量或变量不需要标记lazy修饰符,局部范围的常量或变量从不延迟计算

类型属性(Type Properties):声明关键字static,通过类型本身来调用,而非通过实例调用(C语言中称静态)

1.为某个类型本身定义的属性,用于定义某个类型所有实例共享的数据,无论创建多少个实例,这些类型属性都只有唯一的一份,可为常量或变量

2.必须给存储型类型的类型属性指定默认值,因为类型本身没有构造器,也就无法在初始化过程中使用构造器给类型属性赋值。

3.存储型类型属性是延迟初始化的,它们只有在第一次被访问的时候才会被初始化,即使它们被多个线程同时访问,系统也保证只会对其进行一次初始化,并且不需要对其使用lazy修饰符。

4.在为类定义计算型类型属性时,可以改用关键字class来支持子类对父类的实现进行重写

可延迟小结:

1.延迟属性,用lazy var定义的属性

2.自动闭包,延迟执行,只有被调用时才执行

3.全局变量或常量,是延迟计算的,不用lazy标记

4.存储型的类型属性,是延迟初始化的,第一次被访问时才会被初始化

5.指定清理操作:defer{...}内的语句的执行延迟到当前的作用域退出之前

*/

struct Point {

var x = 0.0, y = 0.0

}

struct Size {

var width = 0.0, height = 0.0

}

struct Cuboid {

lazy var yanchi = Point(x:1.0,y:2.0)  //延迟属性,只有在被调用时才创建

var width = 0.0, height = 0.0, depth = 0.0

var volume: Double {           //属性volume为只读计算属性,它省略了get和{}

return width * height * depth

}

}

struct Rect {

var origin = Point()

var size = Size()

var center: Point {  //计算属性必须声明为变量

get {

let centerX = origin.x + (size.width / 2)

let centerY = origin.y + (size.height / 2)

return Point(x: centerX, y: centerY)

}

set(newCenter) {        //set默认参数为(newValue),可省略,也可以自定义参数名

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 initialSquareCenter = square.center  //调用get来获得值

square.center = Point(x: 15.0, y: 15.0)  //调用set来设置值

print("square.origin is now at (\(square.origin.x), \(square.origin.y))")

// 输出 "square.origin is now at (10.0, 10.0)”

//=============观察器===================

class StepCounter {

var totalSteps: Int = 0 {

willSet(newTotalSteps) {

print("更改之前为:\(totalSteps) 更改之后为:\(newTotalSteps)")

}

didSet {

if totalSteps > oldValue  {

print("改完后的值为:\(totalSteps),新值-旧值=\(totalSteps - oldValue)")

}

}

}

}

let stepCounter = StepCounter()

stepCounter.totalSteps = 200   //存储属性totalSteps的值被改为200之前先调用willSet,改完后调用didSet

stepCounter.totalSteps = 896

//==============类型属性=====================

struct SomeStructure {

static var storedTypeProperty = "Some value."   //必须为所有的static的存储类型赋初始值

static var computedTypeProperty: Int {

return 1

}

}

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 27

}

class var overrideableComputedTypeProperty: Int {   //定义为在子类中可以将该属性重写

return 107

}

}

print(SomeStructure.storedTypeProperty)      //类型属性是通过类型本身的点语法来访问,而不是通过实例

// 输出 "Some value."

SomeStructure.storedTypeProperty = "Another value."

print(SomeStructure.storedTypeProperty)

// 输出 "Another value.”

print(SomeEnumeration.computedTypeProperty)

// 输出 "6"

print(SomeClass.computedTypeProperty)

// 输出 "27"

//==========

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

print(leftChannel.currentLevel)

// 输出 "7"

print(AudioChannel.maxInputLevelForAllChannels)

// 输出 "7"

rightChannel.currentLevel = 11

print(rightChannel.currentLevel)

// 输出 "10"

print(AudioChannel.maxInputLevelForAllChannels)

// 输出 "10"

swift学习笔记之-属性的更多相关文章

  1. Swift学习笔记(13)--属性 (Properties)

    普通属性用var和let即可,本文不做详述 1.延迟存储属性 延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性.在属性声明前使用@lazy来标示一个延迟存储属性. class DataImp ...

  2. 【swift学习笔记】二.页面转跳数据回传

    上一篇我们介绍了页面转跳:[swift学习笔记]一.页面转跳的条件判断和传值 这一篇说一下如何把数据回传回父页面,如下图所示,这个例子很简单,只是把传过去的数据加上了"回传"两个字 ...

  3. Swift学习笔记(一)搭配环境以及代码运行成功

    原文:Swift学习笔记(一)搭配环境以及代码运行成功 1.Swift是啥? 百度去!度娘告诉你它是苹果最新推出的编程语言,比c,c++,objc要高效简单.能够开发ios,mac相关的app哦!是苹 ...

  4. swift学习笔记之--类的计算属性

    1,Swift中类可以使用计算属性,即使用get和set来间接获取/改变其他属性的值,代码如下 class Calcuator{ ; ; var sum:Int{ get{ return a + b ...

  5. swift学习笔记5——其它部分(自动引用计数、错误处理、泛型...)

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  6. swift学习笔记4——扩展、协议

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  7. swift学习笔记3——类、结构体、枚举

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  8. swift学习笔记1——基础部分

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  9. 记录:swift学习笔记1-2

    swift还在不断的更新做细微的调整,都说早起的鸟儿有虫吃,那么我们早点出发吧,趁着国内绝大多数的coder们还没有开始大范围普遍应用. 网上有些大神说:swift很简单!我不同意这个观点,假如你用h ...

随机推荐

  1. 拓扑排序(三)之 Java详解

    前面分别介绍了拓扑排序的C和C++实现,本文通过Java实现拓扑排序. 目录 1. 拓扑排序介绍 2. 拓扑排序的算法图解 3. 拓扑排序的代码说明 4. 拓扑排序的完整源码和测试程序 转载请注明出处 ...

  2. Yii2的深入学习--别名(Aliases)

    在之前自动加载机制的文章中,我们有提到别名,提到 getAlias 方法,大家当时可能不太清楚,这到底是什么,今天我们就来说一下别名. 别名用来表示文件路径和 URL,这样就避免了将一些文件路径.UR ...

  3. C#编写简单的聊天程序

    这是一篇基于Socket进行网络编程的入门文章,我对于网络编程的学习并不够深入,这篇文章是对于自己知识的一个巩固,同时希望能为初学的朋友提供一点参考.文章大体分为四个部分:程序的分析与设计.C#网络编 ...

  4. Linux - Screen

    GNU's Screen homepage Screen是由GNU计划开发的用于命令行终端切换的自由软件,可以看作是窗口管理器的命令行界面版本. 可以通过该软件同时连接多个本地或远程的命令行会话,并在 ...

  5. TCP与UDP在socket编程中的区别

    一.TCP与UDP的区别 基于连接与无连接  对系统资源的要求(TCP较多,UDP少)  UDP程序结构较简单  流模式与数据报模式  TCP保证数据正确性,UDP可能丢包  TCP保证数据顺序,UD ...

  6. Laravel学习

    Laravel是个很强大的PHP框架,它剔除了开发中Web开发中比较痛苦的过程,提供了验证(authentication),路由(routing),Session和缓存(caching)等开发过程中常 ...

  7. 实现jquery.ajax及原生的XMLHttpRequest跨域调用WCF服务的方法

    关于ajax跨域调用WCF服务的方法很多,经过我反复的代码测试,认为如下方法是最为简便的,当然也不能说别人的方法是错误的,下面就来上代码,WCF服务定义还是延用上次的,如: namespace Wcf ...

  8. 需要正确安装 Microsoft.Windows.ShellExperienceHost 和 "Microsoft.Windows.Cortana" 应用程序。

    windows 10 开始菜单修复工具 Win10开始菜单修复工具出现的原因,自从升级到Windows  10,一直BUG不断,而其中有一个BUG非常的让你印象深刻,就是开始菜单无响应,你用着用着电脑 ...

  9. 【原创】Kakfa common包源代码分析

    初一看common包的代码吓了一跳,这么多scala文件!后面仔细一看大部分都是Kafka自定义的Exception类,简直可以改称为kafka.exceptions包了.由于那些异常类的名称通常都定 ...

  10. 解决在IE中获取数据的缓存问题,运行环境为node.js

    IE下默认会开启缓存策略,不管是页面还是通过ajax请求的数据都会议一个url,url是uri(统一资源定位符)的实例,url就是资源的标识符. 写一个demo进行验证,测试环境:IE8,node.j ...