12.2 计算属性
计算属性本身不存储数据,而是从其他存储属性中计算得到数据。与存储属性不同,类、结构体和枚举都可以定义计算属性。
12.2.1 计算属性概念
计算属性提供了一个getter(取值访问器)来获取值,以及一个可选的setter(设置访问器)来间接设置其他属性或变量的值。计算属性的语法格式如下:
面向对象类型 类型名 { ①
存储属性 ②
......
var 计算属性名 : 属性数据类型 { ③
get { ④
return 计算后属性值 ⑤
} ⑥
set (新属性值) { ⑦
......
} ⑧
} ⑨
}
计算属性的语法格式比较混乱,这里我们解释一下。第①行的“面向对象类型”包括类、结构体和枚举3种。第②行的“存储属性”表示有很多存储属性。
事实上,第③~⑨行代码才是定义计算属性,变量必须采用var
声明。第④~⑥行代码是getter访问器,它其实是一个方法,在访问器中对属性进行计算。最后在第⑤行代码必须使用return
语句将计算结果返回。
第⑦~⑧行代码是setter访问器,其中第⑦行代码中,“新属性值”是要赋值给属性值。
定义计算属性比较麻烦,要注意后面的几个大括号的对齐关系。
我们先看一个示例:
import UIKit ①
class Employee {
var no : Int = 0
var firstName : String = "Tony" ②
var lastName : String = "Guan" ③
var job : String?
var salary : Double = 0
lazy var dept : Department = Department()
var fullName : String { ④
get {
return firstName + "." + lastName ⑤
}
set (newFullName) { ⑥
var name = newFullName.componentsSeparatedByString(".") ⑦
firstName = name[0]
lastName = name[1]
}
}
}
struct Department {
let no : Int = 0
var name : String = ""
}
var emp = Employee()
println(emp.fullName) ⑧
emp.fullName = "Tom.Guan" ⑨
println(emp.fullName) ⑩
上述代码第①行是引入UIKit框架,第②行代码是定义员工的firstName
存储属性,第③行代码是定义员工的lastName
存储属性。为了获得fullName
(全名),fullName = firstName . lastName
,不需要定义一个fullName
存储属性,而是可以通过firstName
和lastName
拼接(计算)而成。
第④行代码直接定义fullName
计算属性。第⑤行是返回拼接的结果。第⑥行代码中的newFullName
是要存储传递进来的参数值,set (newFullName)
可以省略如下形式,使用Swift
默认名称newValue
替换newFullName
。
set {
var name = newValue.componentsSeparatedByString(".")
firstName = name[0]
lastName = name[1]
}
代码第⑦行是使用String
的字符串分割方法componentsSeparatedByString
,指定逗号为字符串的分割符号,分割方法返回的是String
数组。
第⑧行代码println(emp.fullName)
是调用属性的getter访问器,取出属性值。第⑨行代码emp.fullName = "Tom.Guan"
是调用属性的setter访问器,给属性赋值。
12.2.2 只读计算属性
计算属性可以只有getter访问器,没有setter访问器,这就是只读计算属性。指定计算属性不仅不用写setter访问器,而且get{}
代码也可以省略。与上一节相比,代码将大大减少。修改上一节示例为只读计算属性,代码如下:
class Employee {
var no : Int = 0
var firstName : String = "Tony"
var lastName : String = "Guan"
var job : String?
var salary : Double = 0
lazy var dept : Department = Department()
var fullName : String { ①
return firstName + "." + lastName
}
}
struct Department {
let no : Int = 0
var name : String = ""
}
var emp = Employee()
println(emp.fullName)
只读计算属性经过简化后,第①行代码是更加简洁的setter访问器。只读计算属性不能够赋值,下列语句是错误的。
emp.fullName = "Tom.Guan"
12.2.3 结构体和枚举中的计算属性
前面介绍的示例都是类的计算属性,本节将介绍一些结构体和枚举中的计算属性,从而比较它们的差异。
示例代码如下:
struct Department { ①
let no : Int = 0
var name : String = "SALES"
var fullName : String { ②
return "Swift." + name + ".D"
}
}
var dept = Department()
println(dept.fullName) ③
enum WeekDays : String { ④
case Monday = "Mon."
case Tuesday = "Tue."
case Wednesday = "Wed."
case Thursday = "Thu."
case Friday = "Fri."
var message : String { ⑤
return "Today is " + self.toRaw() ⑥
}
}
var day = WeekDays.Monday
println(day.message) ⑦
上述代码第①行定义了结构体Department
,第②行定义了只读属性fullName
,第③行是读取fullName
属性。
第④行定义了枚举类型WeekDays
,第⑤行定义了只读属性message
,第⑥行代码中使用了self.toRaw()
语句将当前实例值转换为原始值,其中self
代表当前实例,toRaw()
方法是转换为原始值,否则不能进行字符串拼接。代码第⑦行是读取message
属性。