通过使用可选链式调用可以调用多层属性、方法和下标。这样可以在复杂的模型中向下访问各种子属性,并且判断能否访问子属性的属性、方法和下标。
下面这段代码定义了四个模型类,这些例子包括多层可选链式调用。为了方便说明,在 Person
和 Residence
的基础上增加了 Room
类和 Address
类,以及相关的属性、方法以及下标。
Person
类的定义基本保持不变:
class Person {
var residence: Residence?
}
Residence
类比之前复杂些,增加了一个名为 rooms
的变量属性,该属性被初始化为 [Room]
类型的空数组:
class Residence {
var rooms: [Room] = []
var numberOfRooms: Int {
return rooms.count
}
subscript(i: Int) -> Room {
get {
return rooms[i]
}
set {
rooms[i] = newValue
}
}
func printNumberOfRooms() {
print("The number of rooms is \(numberOfRooms)")
}
var address: Address?
}
现在 Residence
有了一个存储 Room
实例的数组,numberOfRooms
属性被实现为计算型属性,而不是存储型属性。numberOfRooms
属性简单地返回 rooms
数组的 count
属性的值。
Residence
还提供了访问 rooms
数组的快捷方式,即提供可读写的下标来访问 rooms
数组中指定位置的元素。
此外,Residence
还提供了 printNumberOfRooms
方法,这个方法的作用是打印 numberOfRooms
的值。
最后,Residence
还定义了一个可选属性 address
,其类型为 Address?
。Address
类的定义在下面会说明。
Room
类是一个简单类,其实例被存储在 rooms
数组中。该类只包含一个属性 name
,以及一个用于将该属性设置为适当的房间名的初始化函数:
class Room {
let name: String
init(name: String) { self.name = name }
}
最后一个类是 Address
,这个类有三个 String?
类型的可选属性。buildingName
以及 buildingNumber
属性分别表示大厦的名称和号码,第三个属性 street
表示大厦所在街道的名称:
class Address {
var buildingName: String?
var buildingNumber: String?
var street: String?
func buildingIdentifier() -> String? {
if buildingName != nil {
return buildingName
} else if let buildingNumber = buildingNumber, let street = street {
return "\(buildingNumber) \(street)"
} else {
return nil
}
}
}
Address
类提供了 buildingIdentifier()
方法,返回值为 String?
。 如果 buildingName
有值则返回 buildingName
。或者,如果 buildingNumber
和 street
均有值,则返回两者拼接得到的字符串。否则,返回 nil
。