每天学一点Swift----面向对象上(十)

2017-06-01  本文已影响16人  冯可乐同学

十二.可选链

1.对于前面的学习的可选类型:Swift的所有类型默认不能接受nil值,如果程序想让某种数据类型接受nil值,则必须将这种数据类型包装成可选类型。——两种方法:在原有的类型后面加?后缀,要进行强制解析;在原有的类型后加!后缀,由Swift隐式解析。

2.可选链正是用于处理这里可选类型的属性、方法、下标等的。

3.为了更好的理解,直接从代码例子入手:

下面的定义了3个类,这3个类之间存在关联关系,而且程序使用了可选类型类维护它们之间的关联关系:

class Customer

{

var name = "xx顾客"

var emp : Employee?//注意这里有个问号----强制解析

init(name : String)

{

self.name = name

}

}

class Employee

{

var name = "xx职工"

var title = "销售"

var comp : Company!//注意这里有个感叹号----隐式解析

init(name : String, title : String)

{

self.name = name;

self.title = title

}

}

class Company

{

var name = "xx公司"

var addr = ""

init(name : String, addr : String)

{

self.name = name

self.addr = addr

}

}

3个类的关系是:顾客有一个专门为他负责的职工,职工是属于某个公司的。实例化如下:

var customer = Customer(name : "习大大")

var employee = Employee(naem : "马云", title : "销售")

customer.emp = employee

var company(name: "阿里巴巴", addr: "杭州")

employee.comp = company

//这里就可以获取到:为顾客习大大服务的职工所在的公司名称是:阿里巴巴

print("为\(customer.name)服务的职工坐在的公司名称是:\(c.emp!.comp.name)")//注意,emp后面有一个感叹号

4.上面程序中,因为Customer的emp属性类型是Employee?可选类型,因此在程序中使用Customer的emp属性必须使用感叹号进行强制解析。而Employee的comp属性是Company!可选类型,因此程序不需要强制解析,由Swift进行隐式解析即可。

5.对于上面的程序的来说,因为所有需要关联的地方都没有遗漏,所以上面程序可以正确的运行。但是对于下面的情况则会有不同的结果:

var c2 = Customer(name : "小明")

var emp = Employee(name : "小小明", title : "客服")

print("为\(c2.name)服务的职工所在的公司名称是\(c2.emp!.comp.name)")

var c3 = Customer(name : "小红")

print("为\(c3.name)服务的职工所在的公司的名称是:\(c3.emp!.comp.name)")

----对于c2来说,Employee实例所关联的Company为nil,因此程序在进行隐式解析可选类型时将会导致运行错误

----对于c3来说,c3连Employee的实例都没有关联,因此,程序会对c3.emp!进行强制解析得到nil,也会导致运行时出错

----上面两段代码,在编译时可以正常通过,但是运行时就会报错:fatal error

6.通过上面的会导致出错的例子可以看出,强制解析或隐式解析存在一个缺点:只要访问链中任何一次访问的返回值是nil,程序就会导致错误。

7.将上面访问链中强制解析的感叹号换成问号后缀,在隐式解析的后面也添加问号后缀,这就是可选链的访问方式。

8.可选链是一种更加“智能”的方式,可选链会自动判断程序访问的关联实例是否为nil:

(1)如果关联实例不为nil,可选链会自动解析可选类型所包装的值----就像隐式解析一样。

(2)如果关联的实例为nil,可选链不会导致运行时错误,可选链将返回一个nil。即,程序的结果为nil。

将上面5中的输出代码修改如下:

print("为\(c2.name)服务的职工所在的公司的名称是:\(c2.emp?.comp.name)")//输出为nil

print("为\(c3.name)服务的职工所在的公司的名称是:\(c3.emp?.comp.name)")//输出为nil

9.可选链不仅可以用于访问属性,也可以用于调用方法。举个栗子:在刚开始的Customer类增加以下代码:

//定义一个常量类型的emp数组,用于模拟系统中所有员工

let employees = {

Employee(name : "职工1", title : "销售1")

Employee(name : "职工2", title : "销售2")

Employee(name : "职工3", title : "销售3")

Employee(name : "职工4", title : "客服1")

Employee(name : "职工5", title : "客服2")

}

//定义一个方法,该方法可根据员工的名称返回对应的员工信息,返回值为可选类型

func findEmp(empName : String) -> Employee!----注意,这里有个感叹号

{

for emp int employees

{

if emp.name == empName

return emp

}

return nil

}

10.上面的程序中,调用Customer实例的findEmp方法是,如果进行强制解析或隐式解析该返回值,并用该返回值调用方法时就有可能导致运行时错误。但如果程序使用可选链就可以避免错误,使用可选链的代码如下:

c3.findEmp("嫦娥")?.info()

c3.findEmp("KoBe")?.info()

11.当下标返回值类型为可选类型时,下标的返回值同样有可能为nil,此时可对下标使用可选链。举个栗子:

var dict = [Int : Customer]()

dict[1] = Customer(name : "唐僧")

dict[2] = Customer(name : "悟空")

dict[3] = Customer(name : "八戒")

dict[4] = Customer(name : "沙僧")

dict[1]?.findEmp("白龙马")?.info()----第二个问号那里返回nil

dict[2]?.findEmp("白龙马")?.info()——第一个问号那里返回nil

上一篇下一篇

猜你喜欢

热点阅读