您的位置:首页 > 移动开发 > Swift

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

2017-06-01 22:49 211 查看
十二.可选链
  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

上一篇:每天学一点Swift----面向对象上(九)
下一篇:每天学一点Swift----面向对象上(十)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  swift