接下来就讨论一下可选链,类型属性和类型方法,构造器
1.可选链是用于处理可选类型的属性,方法和下标
2.使用可选链代替强制解析
3.调用方法
4.调用下标
//创建3个关联类
class customer{
var name = ""
var emp: employee?
init(name: String){
self.name = name
}
}
class company {
var name = ""
var addr = ""
init(name: String , addr: String){
self.name = name
self.addr = addr
}
}
class employee{
var name = ""
var title = "行政"
var company: company!
init(name: String, title: String){
self.name = name
self.title = title
}
func info() {
print("本员工名为\(self.name),职位为\(self.title)")
}
}
var c = customer(name: "tom")
var emp = employee(name: "jack", title: "student")
//设置customer关联的employee实例
c.emp = emp
//设置empoyee关联的compony实例
emp.company = company(name: "swift", addr:"shanghai")
print("为\(c.name)服务的公司是:\(c.emp!.company.name)")
//第二种情况
var c2 = customer(name: "lucky")
//设置customer关联的employee实例
c2.emp = employee(name:"helly", title: "客服")
//print(c2.emp!.company.name)//此时是没有为company赋值的,它的值为nil.为此使用可选链访问属性
//使用可选链访问属性
/*
可选链的访问方式:将强制解析的!换成?,即是是隐式解析后面也要添加?
*/
print(c2.emp?.company?.name)//输出为nil
//可选链会自动防伪关联属性的可选情况,自动判别是否为nil
通过可选链来访问方法和下标
首先做可选链访问方法
//创建3个关联类
class customer{
var name = ""
var emp: employee?
init(name: String){
self.name = name
}
//定义一个常量类型的employee数组,用于模拟系统中所有的员工
let employees = [employee(name: "张三" , title: "销售"),
employee(name: "小明" , title: "售后"),
employee(name: "han" , title: "普通员工"),
employee(name: "better" , title: "销售主管")
]
//定义一个方法,该方法可根据员工名返回对应的员工,返回值为可选类型
func findemp(empname: String) -> employee!{
for emp in employees{
if emp.name == empname {
return emp
}
}
return nil
}
}
class company {
var name = ""
var addr = ""
init(name: String , addr: String){
self.name = name
self.addr = addr
}
}
class employee{
var name = ""
var title = "行政"
var company: company!
init(name: String, title: String){
self.name = name
self.title = title
}
func info() {
print("本员工名为\(self.name),职位为\(self.title)")
}
}
//通过可选链来调用方法
var c3 = customer(name: "paul")
c3.findemp(empname: "张三")?.info()
c3.findemp(empname: "小明")?.info()
可选链访问下标
//可选链访问下标
var dict = [Int : customer]()
dict[1] = customer(name: "han")
dict[2] = customer(name: "angle")
dict[1]?.findemp(empname: "better")?.info()
dict[4]?.findemp(empname: "better")?.info()
类型属性和类型方法
值类型的类型属性
//1.值类型的类型属性
enum season {
//为枚举定义类型存储属性,使用可选类型,系统将其初始化为nil
static var desc : String?
//为枚举定义类型存储属性,且声明为常量
static let name = "季节"
static var info: String{
get{
return "代表季节的枚举,其desc为:\(desc)"
}
set{
print("程序尝试对info计算属性进行赋值:\(newValue)")
}
}
}
//对season枚举的类型属性赋值
season.desc = "季节类"
print(season.name)
season.info = "新的info"
print(season.info)
//结构体可以包含实例计算属性,不能包含实例存储属性
struct fkrange{
//为结构体定义类型存储属性,使用可选类型,系统将其初始化为nil
static var desc : String?
//为结构体定义类型存储属性,且声明为常量
static let maxwidth = 10000
static let maxheight = 40000
//定义类型计算属性,该属性只有get部分,是一个只读属性
static var maxarea: Int{
return maxwidth * maxheight
}
}
fkrange.desc = "描述范围的结构体"
print(fkrange.desc)
print(fkrange.maxwidth)
print(fkrange.maxheight)
print(fkrange.maxarea)
class在类中修饰属性和方法
类的属性:
//类的类型属性
class user{
//为类定义类型计算属性
class var namemaxlength: Int {
get{
return 24
}
set{
print(newValue)
}
}
}
print(user.namemaxlength)
user.namemaxlength = 20
//类中不可以定义类型存储属性,只能包含类型存储属性
值类型的类型方法
//值类型的类型方法
enum season2{
//为枚举定义类型存储属性,使用可选类型,系统将其初始化为nil
static var desc : String?
//为枚举定义类型存储属性,且声明为常量
static let name = "季节"
//定义无参数的类型方法
static func info(){
print("季节类的info方法")
}
//定义一个带参数的类型方法
static func setdesc(desc : String){
self.desc = desc
}
}
season2.info()
season2.setdesc(desc: "季节变化的枚举")
print(season2.desc)
类的类型方法:
//类的类型方法
class math{
//类中不允许定义类型存储属性,使用类型计算属性代替
class var pi: Double{
return 3.1415
}
class func abs(value: Double) -> Double{
return value < 0 ? -value : value
}
//定义类型方法,取消第二个形参的外部形参名
class func pow(base: Double, _ exponet: Int) -> Double{
var result = 1.0
for idx in 1...exponet{
result *= base
}
return result
}
//定义类型方法,类型方法可以直接访问类型属性
class func radian2degree(radian: Double) -> Double{
return radian*180 / pi
}
//定义类型方法,类型方法可通过self应用类型属性
class func degree2radian(degree: Double) -> Double{
return degree * self.pi / 180
}
}
print(math.pi)
print(math.pow(base: 2, 5))
print(math.radian2degree(radian: 1.3))
print(math.degree2radian(degree: 1.2))
构造器
1.swift构造器构造出来的实例有系统隐式返回
2.构造器的作用完成结构体和类实例存储属性的初始化
3.为实例存储属性赋初值的时机:
1>定义实例存储属性时赋初始值
2>在构造器中为实例存储属性赋初始值
实例存储属性的初始化分类:
1>定义实例存储属性时,显示指定了初始值
2>实例存储属性的类型为可选类型
3>系统提供的默认构造器为实例存储属性提供初始值
4>显示提供的构造器为实例存储属性提供初始值
类和结构体的构造器
swift只为类提供一个无参数的构造器
swift为结构体提供2个构造器:无参数的构造器和初始化所有实例存储属性的构造器
可能失败的构造器
结构体,枚举或者是类不能成功返回这个类型的实例。如:用户传入的参数不对,会让构造器的创建失败,而此时就需要可能失败的构造器
1.使用init?或者init!来进行定义
2.在构造器执行体中return nil 标示构造器失败
3.swift不允许构造2个形参列表的构造器,即是一个是可能失败的构造器,一个是普通的构造器也不行。
构造器的外部形参名
//构造器的外部形参名
struct fkpoint{
var left: Int = 0
var top: Int = 0
//定义带两个参数的构造器,并为第二个参数显示指定外部形参名
init(left: Int , y top: Int){
self.left = left
self.top = top
}
}
var p1 = fkpoint(left: 20, y: 12)
取消构造器的外部形参名
//取消构造器的外部形参名
class person {
var name: String?
var gender: String?
var age = 0
//由于该类中前2个实例存储属性使用了可选类型,后一个存储属性指定了初始值
//因此该结构体对构造器没有要求,故此处可以随便定义构造器
//取消构造器参数的外部形参名
init(_ name: String, _ gender: String){
self.name = name
self.gender = gender
}
}
//调用构造器时无需要使用外部形参名
var p = person("虽无空", "南")
print(p.name)
在构造过程中,使用闭包初始化存储属性
//使用闭包或函数为属性设置初始值
struct closureinit {
//使用闭包对test实例属性执行初始化
var test: Int = {
var dt = NSDate()
var gregorian = NSCalendar.current
//定义一个时间字段的旗标,指定将会获取指定月日的信息
var unitflags = NSCalendar.Unit.month | NSCalendar.Unit.day
var comp = gregorian.component(unitflags, from: dt)
//获取当前的月份
var month = Int(comp.month)
return month
}()
}
值类型的构造器重载
//值类型的构造器重载
struct constructoroverload {
var name: String?
var amount: Int?
//提供无参数的构造器
init(){}
//提供带两个参数的构造器来完成构造过程
init(name: String, amount: Int){
self.name = name
self.amount = amount
}
}
//通过无参数构造器创建constructoroverload实例
var oc1 = constructoroverload()
//通过有参数构造器创建constructoroverload
var oc2 = constructoroverload(name: "swift", amount: 8000)
print(oc1.name)
print(oc2.name)
构造器代理
在定义构造器时,通过self,init(实参)来调用其它构造器,来完成实例的部分构造过程
//构造器代理
struct apple{
var name: String
var color: String
var weight: Double!
init(_ name: String , _ color: String)
{
self.name = name
self.color = color
}
//两个参数的构造器
init(name: String, color: String){
self.init( name, color)
}
//为构造器显示指定外部形参名
init(applename n: String, applecolor c: String){
self.init(n, c)
}
}
//可能失败的构造器
//可能失败的构造器
struct cat {
let name: String
init?(name: String){
//如果传入的name参数为空字符串,构造器失败,返回nil
if name.isEmpty {
return nil
}
self.name = name
}
}
enum season {
case spring, summer, autumn, winter
//使用init!定义可能失败的构造器,则改构造器创建的实例可以进行隐式解析
init!(name: Character){
switch name {
case "s":
self = .spring
case "u":
self = .summer
case "a":
self = .summer
case "w":
self = .winter
default:
return nil
}
}
}