一、存储属性:存储常量或者变量
注意:1、给它默认值,2、在构造方法里初始化
二、计算属性
计算属性不直接存储值,而是提供一个getter和一个可以选择的setter
类似java的封装
-访问的时候调用get,赋值调用set
-set内置newValue变量,可以直接调用
-set里面不能给当前的计算属性赋值,否则死循环有赋值语句
-只读计算属性:只提供get,不提供set。在写的时候可以省略get符号
三、类属性
类属性用static修饰
-类属性是和类关联的,不单独属于某一个对象
-只能通过类名访问,这点和java不同
-整个类都只有一份,牵一发而动全身
class Student{
//存储属性
var age:Int = 0
var javaScore:Double = 0.0
var htmlScore:Double = 0.0
//计算属性
var averageScore:Double{
//获取值
get{
print("get被调用")
return (javaScore + htmlScore)/2 //get中必须有return语句
}
//赋值
set{
print("set被调用,\(newValue)")
// self.averageScore = newValue 只要有赋值就会调用set语句,造成死循环
}
}
只读计算属性
var averageScore2:Double{
//获取值
get{
print("get2被调用")
return (javaScore + htmlScore)/2 //get中必须有return语句
}
}
var averageScore3:Double{
//获取值 省略get
print("get3被调用")
return (javaScore + htmlScore)/2 //get中必须有return语句
}
类属性
static var courseCount:Int = 2
}
使用各个属性
var stu = Student()
//使用存储属性
stu.age = 20
stu.javaScore = 99.9
stu.htmlScore = 88.8
//使用计算属性
print(stu.averageScore)
stu.averageScore = 100
//使用只读计算属性
print(stu.averageScore2)
//使用类属性
print(Student.courseCount)//只能通过类名来访问
懒加载属性
懒加载属性的引入
需求:需要对区间进行计算,并且计算量很大,很耗时,最终结果放到resulit变量内
思考:把result属性定义为计算属性有没有什么缺陷?
缺陷:每用一次就访问一次。并不会存储计算结果
改进:用的时候计算,计算一次并把计算结果存储下来--懒加载属性
懒加载的使用:
lazy var 变量:类型 = {代码段}()
-只会赋值一次
-闭包只执行一次,第一次使用后执行并把返回值赋值给属性
class CloseRange{
var start:Int = 0
var end:Int = 1000
//方案一、result为计算属性
/*
var result:Int{
get{
print("开始计算...")
var res = 0
//此时采用求和操作来模拟进行大量计算
for i in self.start...self.end{
res += i
}
return res
}
}
*/
//方案二:result懒加载属性
lazy var result:Int = {
()->Int in
print("开始计算...")
var res = 0
//此时采用求和操作来模拟进行大量计算
for i in self.start...self.end{
res += i
}
return res
}()
}
var range = CloseRange()
print(range.result)
属性观察器
1、监听和响应属性值的变化
2、针对存储属性和类属性值的变化
3、怎么实现?为观察的属性添加观察器
willSet 在赋值之前调用
didSet 在赋新值之后调用
class Student{
//存储属性
var age:Int = 0
var javaScore:Double = 0.0
var htmlScore:Double = 0.0
//计算属性
var averageScore:Double{
//获取值
get{
print("get被调用")
return (javaScore + htmlScore)/2 //get中必须有return语句
}
//赋值
set{
print("set被调用,\(newValue)")
// self.averageScore = newValue 只要有赋值就会调用set语句,造成死循环
}
}
//只读计算属性
var averageScore2:Double{
//获取值
get{
print("get2被调用")
return (javaScore + htmlScore)/2 //get中必须有return语句
}
}
var averageScore3:Double{
//获取值 省略get{}
print("get3被调用")
return (javaScore + htmlScore)/2 //get中必须有return语句
}
//类属性
static var courseCount:Int = 2
属性观察器
var name:String = "test"{
willSet{
print("willSet被调用,newValue的值\(newValue)")
}
didSet{
print("didSet被调用,oldValue的值\(oldValue)")
}
}
}
var stu = Student()
stu.name = "jing"
stu.name = "999"
懒加载属性案例
场景一、位置的定位
class Location{
let latitude:double //经度
let longitude:double//纬度
init(latitude:double,longitude:Double){
self.latitude = latitude
self.longitude = longitude
}
lazy var address:String = {
//进行经纬度分析,非常复杂的计算
return "xxxx"
}()
}
场景二:阅读类APP
//列表页:书名、封面、简介-不需要加载书本的内容
//详情页-阅读
//问题:书本的内容到底啥时候加载到内存里?
// -只有永固点击阅读,加载内容到内存里
class Book{
let name:String = ""
lazy var content:String = {
//从网络中获取
return "xxxx"
}()
}
属性观察器的使用场景
需求:对current属性重新设计,满足如下:
设备,对通电的最大电流值有要求。
- <30,正常赋值
- =30,提醒你已经到最大值
- >30,提醒用户;当前电流太高,操作失败,回到初始值
class Machine{
let max = 30
var current = 10 {
willSet{
if newValue < max{
print("正常赋值")
}else if newValue == max{
print("注意!此时已经到达最大值")
}else if newValue > max{
print("电流太高,操作失败")
}
}
didSet{
if current > max{
print("当前电流太高,已经超过最大值,要恢复原本值")
current = oldValue
}
}
}
}
var m1 = Machine()
m1.current = 20
m1.current = 30
m1.current = 110
print(m1.current)
属性重写
属性重写要遵循一定的原则,不然会报错。
-重写使用关键字override
重写原则:
1、无论继承的是存储属性还是计算属性,子类都可以提供get\set对属性进行重写
2、不可以把继承的属性重写为一个只读属性
3、如果重写时提供了set方法,一定要提供get
4、属性观察器:
-不管父类有没有,子类都可以添加属性观察器
-如果我们的父类已经有了,我们的子类又重写。那么当这个属性发生变化,那么费父类与子类都将被调用
各种属性
class Student{
//存储属性
var age:Int = 0
var javaScore:Double = 0.0
var htmlScore:Double = 0.0
//计算属性
var averageScore:Double{
//获取值
get{
print("get被调用")
return (javaScore + htmlScore)/2 //get中必须有return语句
}
//赋值
set{
print("set被调用,\(newValue)")
// self.averageScore = newValue 只要有赋值就会调用set语句,造成死循环
}
}
// 只读计算属性
var averageScore2:Double{
//获取值
get{
print("get2被调用")
return (javaScore + htmlScore)/2 //get中必须有return语句
}
}
var averageScore3:Double{
//获取值 省略get
print("get3被调用")
return (javaScore + htmlScore)/2 //get中必须有return语句
}
//类属性
static var courseCount:Int = 2
}
//属性观察器
var name:String = "test"{
willSet{
print("willSet被调用,newValue的值\(newValue)")
}
didSet{
print("didSet被调用,oldValue的值\(oldValue)")
}
}
重写方法
class MiddleStudent:Student{
//子类通过get\set堆属性进行重写
override var age:Int{
get{
print("get被调用")
return 18
}
set{
}
}
/* override var averageScore2:Double{//错的
get{
print()
return
}
}*/
override var name:String{
willSet{
print("willSet被调用,newValue的值\(newValue)")
}
didSet{
print("didSet被调用,oldValue的值\(oldValue)")
}
}
}
结果
var ms = MiddleStudent()
ms.name = "中学生"
print(ms.name)