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 什么是 ...
随机推荐
- Android:Notification的生成与取消
MainActivity.java: package com.example.notificationdemo; import android.app.Activity; import android ...
- CentOS 如何安装git server + Gitolite 【配置不成功需要再测试2015-8-20】
安装git 关于安装git 可以参考 http://gitolite.com/gitolite/install.html 里面有官方的介绍 1. Git 的工作需要调用 curl,zlib,open ...
- saltstack:使用教程之二高级模块用法Grains、Pillar
1.grains用法: 在客户端服务启动的时候收集客户的基础信息,在配置发生变化后也可以通过master重新同步 显示一个客户端的所有项目: [root@node5 ~]# salt "no ...
- JVM调优总结(九)-新一代的垃圾回收算法
垃圾回收的瓶颈 传统分代垃圾回收方式,已经在一定程度上把垃圾回收给应用带来的负担降到了最小,把应用的吞吐量推到了一个极限.但是他无法解决的一个问题,就是Full GC所带来的应用暂停.在一些对实时性要 ...
- linux下shutdown无法关闭tomcat进程的解决方式
1.问题 笔者在linux下发现使用tomcat6.0.41自带的./shutdown.sh常常无法停止进程,导致各种问题的发生,令笔者相当反感! 2.解决方式一: 查找到全部的tomcat进程 $ ...
- PHP - 图像处理
第14章 处理图像 学习要点: 1.创建图像 2.简单小案例 在PHP5中,动态图象的处理要比以前容易得多.PHP5在php.ini文件中包含了GD扩展包,只需去掉GD扩展包的相应注释就可以正常使用了 ...
- c语言,结构体
数据类型分为4种, 简单数据类型,构造数据类型,指针数据类型,空类型. 结构体属于构造数据类型,用struct标识. 声明一个结构体: Typedef struct和struct c c++ typ ...
- 【jQuery】smartMenu右键自定义上下文菜单插件(似web QQ)
(前端用重点整理博客地址)链接地址:http://www.cnblogs.com/atree/archive/2011/06/30/jQuery-smartMenu-javascript.html 一 ...
- jquery 中获取所有选中的checkbox的用法
以往还错误的把$("input[type='checkbox'][checked]") 是正确的用法,奇怪的是:这样用之前确实是好用的,单当我页面中的html内容超过1000行时, ...
- C++多继承的好处是增加了弹性和灵活性,Delphi类强迫单继承TObject是为了提供许多强大功能
要说灵活性,是C++更强.我自己开发已经好几次碰到需要多继承的情况了. 但是Delphi强迫继承TObject,虽然是单继承,但是提供了相当多的强力功能.要说强大,那还是Delphi当仁不让. 摘自& ...