Swift编程语言学习9—— 存储属性和计算属性
属性将值跟特定的类、结构或枚举关联。存储属性存储常量或变量作为实例的一部分,计算属性计算(而不是存储)一个值。计算属性能够用于类、结构体和枚举里,存储属性仅仅能用于类和结构体。
存储属性和计算属性通经常使用于特定类型的实例,可是,属性也能够直接用于类型本身,这样的属性称为类型属性。
另外,还能够定义属性监视器来监控属性值的变化,以此来触发一个自己定义的操作。属性监视器能够加入到自己写的存储属性上,也能够加入到从父类继承的属性上。
存储属性
简单来说,一个存储属性就是存储在特定类或结构体的实例里的一个常量或变量,存储属性能够是变量存储属性(用keywordvar定义),也能够是常量存储属性(用keywordlet定义)。
能够在定义存储属性的时候指定默认值,请參考构造过程一章的默认属性值一节。也能够在构造过程中设置或改动存储属性的值,甚至改动常量存储属性的值,请參考构造过程一章的在初始化阶段改动常量存储属性一节。
以下的样例定义了一个名为FixedLengthRange的结构体,他描写叙述了一个在创建后无法改动值域宽度的区间:
- struct FixedLengthRange {
- var firstValue: Int
- let length: Int
- }
- var rangeOfThreeItems =FixedLengthRange(firstValue: 0, length: 3)
- // 该区间表示整数0,1,2
- rangeOfThreeItems.firstValue = 6
- // 该区间如今表示整数6,7,8
FixedLengthRange的实例包括一个名为firstValue的变量存储属性和一个名为length的常量存储属性。在上面的样例中,length在创建实例的时候被赋值,由于它是一个常量存储属性,所以之后无法改动它的值。
常量和存储属性
假设创建了一个结构体的实例并赋值给一个常量,则无法改动实例的不论什么属性,即使定义了变量存储属性:
- let rangeOfFourItems =FixedLengthRange(firstValue: 0, length: 4)
- // 该区间表示整数0,1,2,3
- rangeOfFourItems.firstValue = 6
- // 虽然firstValue诗歌变量属性,这里还是会报错
由于rangeOfFourItems声明成了常量(用letkeyword),即使firstValue是一个变量属性,也无法再改动它了。
这样的行为是因为结构体(struct)属于值类型。当值类型的实例被声明为常量的时候,它的全部属性也就成了常量。
属于引用类型的类(class)则不一样,把一个引用类型的实例赋给一个常量后,仍然能够改动实例的变量属性。
延迟存储属性
延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用@lazy来标示一个延迟存储属性。
注意:
必须将延迟存储属性声明成变量(使用varkeyword),由于属性的值在实例构造完毕之前可能无法得到。而常量属性在构造过程完毕之前必需要有初始值,因此无法声明成延迟属性。
延迟属性非常实用,当属性的值依赖于在实例的构造过程结束前无法知道详细值的外部因素时,或者当属性的值须要复杂或大量计算时,能够仅仅在须要的时候来计算它。
以下的样例使用了延迟存储属性来避免复杂类的不必要的初始化。样例中定义了DataImporter和DataManager两个类,以下是部分代码:
- class DataImporter {
- /*
- DataImporter 是一个将外部文件里的数据导入的类。
- 这个类的初始化会消耗不少时间。
- */
- var fileName = "data.txt"
- // 这是提供数据导入功能
- }
- class DataManager {
- @lazy var importer = DataImporter()
- var data = String[]()
- // 这是提供数据管理功能
- }
- let manager = DataManager()
- manager.data += "Some data"
- manager.data += "Some more data"
- // DataImporter 实例的 importer 属性还没有被创建
DataManager类包括一个名为data的存储属性,初始值是一个空的字符串(String)数组。尽管没有写出所有代码,DataManager类的目的是管理和提供对这个字符串数组的訪问。
DataManager的一个功能是从文件导入数据,该功能由DataImporter类提供,DataImporter须要消耗不少时间完毕初始化:由于它的实例在初始化时可能要打开文件,还要读取文件内容到内存。
DataManager也可能不从文件里导入数据。所以当DataManager的实例被创建时,不是必需创建一个DataImporter的实例,更明智的是当用到DataImporter的时候才去创建它。
因为使用了@lazy,importer属性仅仅有在第一次被訪问的时候才被创建。比方訪问它的属性fileName时:
- println(manager.importer.fileName)
- // DataImporter 实例的 importer 属性如今被创建了
- // 输出 "data.txt”
存储属性和实例变量
假设您有过 Objective-C 经验,应该知道有两种方式在类实例存储值和引用。对于属性来说,也能够使用实例变量作为属性值的后端存储。
Swift 编程语言中把这些理论统一用属性来实现。Swift中的属性没有相应的实例变量,属性的后端存储也无法直接訪问。这就避免了不同场景下訪问方式的困扰,同一时候也将属性的定义简化成一个语句。一个类型中属性的所有信息——包含命名、类型和内存管理特征——都在唯一一个地方(类型定义中)定义。
计算属性
除存储属性外,类、结构体和枚举能够定义计算属性,计算属性不直接存储值,而是提供一个 getter 来获取值,一个可选的 setter 来间接设置其它属性或变量的值。
- 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 {
- get {
- let centerX = origin.x + (size.width / 2)
- let centerY = origin.y + (size.height / 2)
- return Point(x: centerX, y: centerY)
- }
- 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 initialSquareCenter = square.center
- square.center = Point(x: 15.0, y: 15.0)
- println("square.origin is now at(\(square.origin.x), \(square.origin.y))")
- // 输出"square.origin is now at (10.0, 10.0)”
这个样例定义了 3 个几何形状的结构体:
Point封装了一个(x, y)的坐标
Size封装了一个width和height
Rect表示一个有原点和尺寸的矩形
Rect也提供了一个名为center的计算属性。一个矩形的中心点能够从原点和尺寸来算出,所以不须要将它以显式声明的Point来保存。Rect的计算属性center提供了自己定义的 getter 和 setter 来获取和设置矩形的中心点,就像它有一个存储属性一样。
样例中接下来创建了一个名为square的Rect实例,初始值原点是(0, 0),宽度高度都是10。如图所看到的蓝色正方形。
square的center属性能够通过点运算符(square.center)来訪问,这会调用getter 来获取属性的值。跟直接返回已经存在的值不同,getter 实际上通过计算然后返回一个新的Point来表示square的中心点。如代码所看到的,它正确返回了中心点(5, 5)。
center属性之后被设置了一个新的值(15, 15),表示向右上方移动正方形到如图所看到的橙色正方形的位置。设置属性center的值会调用 setter 来改动属性origin的x和y的值,从而实现移动正方形到新的位置。
便捷 setter 声明
假设计算属性的 setter 未定义表示新值的參数名,则能够使用默认名称newValue。以下是使用了便捷 setter 声明的Rect结构体代码:
- struct AlternativeRect {
- 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 {
- origin.x = newValue.x - (size.width / 2)
- origin.y = newValue.y - (size.height / 2)
- }
- }
- }
仅仅读计算属性
仅仅有 getter 没有 setter 的计算属性就是仅仅读计算属性。仅仅读计算属性总是返回一个值,能够通过点运算符訪问,但不能设置新的值。
注意:
必须使用varkeyword定义计算属性,包含仅仅读计算属性,由于他们的值不是固定的。letkeyword仅仅用来声明常量属性,表示初始化后再也无法改动的值。
仅仅读计算属性的声明能够去掉getkeyword和花括号:
- struct Cuboid {
- var width = 0.0, height = 0.0, depth = 0.0
- var volume: Double {
- return width * height * depth
- }
- }
- let fourByFiveByTwo = Cuboid(width: 4.0,height: 5.0, depth: 2.0)
- println("the volume of fourByFiveByTwois \(fourByFiveByTwo.volume)")
- // 输出 "the volumeof fourByFiveByTwo is 40.0"
这个样例定义了一个名为Cuboid的结构体,表示三维空间的立方体,包括width、height和depth属性,另一个名为volume的仅仅读计算属性用来返回立方体的体积。设置volume的值毫无意义,由于通过width、height和depth就能算出volume。然而,Cuboid提供一个仅仅读计算属性来让外部用户直接获取体积是非常实用的。
Swift编程语言学习9—— 存储属性和计算属性的更多相关文章
- Swift面向对象基础(中)——Swift中的存储属性和计算属性
学习来自<极客学院> 1.存储属性:存储在类.结构体里的变量或者常量 2.分为:实例存储属性.类型存储属性 3.所有的存储属性必须显示的指定初始值,在定义时或者构造器当中指定 4.可选类型 ...
- Swift编程语言学习10—— 枚举属性监视器
属性监视器 属性监视器监控和响应属性值的变化,每次属性被设置值的时候都会调用属性监视器.甚至新的值和如今的值同样的时候也不例外. 能够为除了延迟存储属性之外的其它存储属性加入属性监视器,也能够通过重载 ...
- Swift类与结构、存储属性、计算属性、函数与方法、附属脚本等
写了12个Person来复习,不过完成同样的代码需要敲键盘的次数相比OC确实少了很多,这很多应该归功于Swift中不写分号,以及少了OC中的中括号. 一.类与结构体 两者在Swift中差不了多少了 类 ...
- Swift编程语言学习11—— 枚举全局变量、局部变量与类型属性
全局变量和局部变量 计算属性和属性监视器所描写叙述的模式也能够用于全局变量和局部变量,全局变量是在函数.方法.闭包或不论什么类型之外定义的变量,局部变量是在函数.方法或闭包内部定义的变量. 前面章节提 ...
- swift学习笔记之--类的计算属性
1,Swift中类可以使用计算属性,即使用get和set来间接获取/改变其他属性的值,代码如下 class Calcuator{ ; ; var sum:Int{ get{ return a + b ...
- swift 存储属性和计算属性 set{}和get{} didSet{}和willSet{}
首先我们看一段代码: var A:Int = 0 var B:Int = 0 var C:Int { get { return 1 } set { print("Recived new va ...
- 《从零开始学Swift》学习笔记(Day 33)——属性观察者
原创文章,欢迎转载.转载请注明:关东升的博客 为了监听属性的变化,Swift提供了属性观察者.属性观察者能够监听存储属性的变化,即便变化前后的值相同,它们也能监听到. 属性观察者主要有以下两个: l ...
- Swift编程语言学习12 ——实例方法(Instance Methods)和类型方法(Type Methods)
方法是与某些特定类型相关联的函数.类.结构体.枚举都能够定义实例方法:实例方法为给定类型的实例封装了详细的任务与功能.类.结构体.枚举也能够定义类型方法:类型方法与类型本身相关联.类型方法与 Obje ...
- Vue.js 学习笔记 第3章 计算属性
本篇目录: 3.1 什么是计算属性 3.2 计算属性用法 3.3 计算属性缓存 模板内容的表达式常用语简单的运算,当其过长或逻辑复杂时,会难以维护,本章的计算属性就是用于解决该问题的. 3.1 什么是 ...
随机推荐
- windows phone8手机玩玩
背景介绍 北京移动在搞活动,预存话费赠手机活动,因此办理了一个,来玩新手机了. 上手一周了,白色的手机,对我来说配置凑合,主要是想学习wp8手机的开发,这样也有个样机玩玩.开发人员就是这么的喜欢玩. ...
- POJ 2455 网络流 基础题 二分+网络流 dicnic 以及 sap算法
Secret Milking Machine Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8189 Accepted: ...
- rackup工具
gem包rack提供了rackup工具来启动webapplication 下面是一个入门范例,使用 bundler 管理库的一个sinatra应用 在begin文件夹下有三个文件 begin.ru ...
- Windows的TCP协议参数
注册表编辑器:regedit 表项:HKEY_LOCAL_MACHINE\SYSTEM\CurentControlSet\Services\Tcpip\Parameters 窗口扩大因子 & ...
- jquery遍历筛选数组的几种方法和遍历解析json对象
jquery grep()筛选遍历数组 $().ready( function(){ var array = [1,2,3,4,5,6,7,8,9]; var fil ...
- 多文件上传组件FineUploader使用心得
原文 多文件上传组件FineUploader使用心得 做Web开发的童鞋都知道,需要经常从客户端上传文件到服务端,当然,你可以使用<input type="file"/> ...
- dos2unix与unix2dos之学习记录
1. unix2dos与dos2unix这两个tool是用来干什么的? 这首先应该要说明一下背景知识: unix类操作系统下,换行字符是\n: 而早期的dos操作系统,其换行字符是由\r\n组成. 所 ...
- 3DShader之立方体环境映射(cubic environment mapping)
前面讲了球形环境映射,然而目前采用更多的是立方体环境映射.国际惯例:上图先: 1.反射: 2.折射 3.fresnel(反射+折射) 4.色散 好了,大概讲下原理, 立方体纹理我就不多讲了,它以一个3 ...
- ASC(22)H(大数+推公式)
High Speed Trains Time Limit: 4000/2000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) Su ...
- Struts 2中的constant详解
通过对这些属性的配置,可以改变Struts 2 框架的一些默认行为,这些配置可以在struts.xml文件中完成,也可以在struts.properties文件中完成. 1.<constant ...