Swift -6 面向对象基础(下)

来源:互联网 发布:龙腾世纪审判优化补丁 编辑:程序博客网 时间:2024/04/29 17:04

可选链

在原有类型后面添加?,需要强制解析
在原有类型后面添加!,不需要强制解析
Swift的所有类型默认不能接受nil值,但是定义成可选类型就可以了,可选链就是用来处理可选类型的属性的,下标和方法,可以代替强制解析

可选链用于处理可选类型的属性.方法和下标
使用可选链代替强制解析
调用方法
调用下标

创建三个关联类

class Customer {    var name = ""    var emp: Employee?    init(name: String){        self.name = name    }    // 定义一个常量类型的employee数组,用于模拟系统中所有员工    let employees = [        Employee(name: "张三", title: "销售客服"),        Employee(name: "小明", title: "售后客服"),        Employee(name: "Devin", title: "普通客服"),        Employee(name: "Lucy", 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 = "Devin"    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: "Damon")var emp = Employee(name: "Elena", title: "Student")// 设置Customer关联的Employee实例c.emp = emp// 设置Employee关联的Company实例emp.company = Company(name: "苹果", addr: "加利福利亚")print("为\(c.name)服务的公司是:\(c.emp!.company.name)")// 第二种情况var c2 = Customer(name: "Lucy")// 设置Customer关联的Employee实例c2.emp = Employee(name: "Snow", title: "客服")print("为\(c2.name)服务的公司是:\(c2.emp?.company?.name)")// 使用可选链访问属性var c3 = Customer(name: "Paul")print("为\(c3.name)服务的公司是:\(c3.emp?.company?.name)")

使用可选链访问属性

1.可选链访问方式:将强制解析的感叹号换成?,在隐式解析的后面也添加?后缀2.可选链会自动判断程序访问的关联实例是否为nil

使用可选链调用方法

c3.findEmp("张三")?.info()c3.findEmp("小明")?.info()var dict = [Int: Customer]()dict[1] = Customer(name: "Devin")dict[2] = Customer(name: "Angel")

使用可选链访问下标

//dict[1]?.findEmp("Lucy")?.info()dict[4]?.findEmp("Lucy")?.info() // 4这个下标没有值

类型属性和类型方法

1.Swift的类型中可以定义5中成员:属性.方法.下标.构造器和嵌套类型
2.类型属性.实例属性
3.类型方法.实例方法
4.static:在枚举.结构体中修饰的属性.方法
5.class:在类中修饰的属性.方法

值类型的类型属性

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 User {    // 为类定义类型计算属性    class var nameMaxLength: Int {        get{            return 24        }        set{            print("程序尝试对User类的nameMaxLength类型计算属性赋值\(newValue)")        }    }}print(User.nameMaxLength)User.nameMaxLength = 20// 类中不可以定义类型存储属性, 只能包含类型计算属性

值类型的类型方法

enum Season2{    // 为枚举定义类型存储属性, 使用可选类型, 系统将其初始化为nil    static var desc: String?    // 为枚举定义类型存储属性, 且声明为常量    static let name = "季节"    // 定义无参数的类型方法    static func info(){        print("季节类的info方法, 该类的name存储属性为:\(name)")    }    // 定义带一个参数的类型方法    static func setDesc(desc: String){        self.desc = desc    }}Season2.info()Season2.setDesc("描述季节变化的枚举")print(Season2.desc)

类的类型方法

class Math{    // 类不允许定义类型存储属性, 使用类型计算属性代替    class var pi: Double {        return 3.141592653589    }    class func abs(value: Double) -> Double {        return value < 0 ? -value: value    }    // 定义类型方法, 取消第二个形参的外部形参名    class func pow(base: Double, _ exponent: Int) -> Double {        var result = 1.0        for _ in 1...exponent{            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(2, 4))print(Math.radian2Degree(1.57))print(Math.degree2Radian(45))

构造器

1.Swift的构造器构造出来的实例由系统隐式返回2.构造器的作用完成每个类, 结构体中实例存储属性的初始化3.为实例存储属性赋初始值的时机:    1>定义实例存储属性时指定初始值    2>在构造器中为实例存储属性指定初始值实例存储属性的初始化分类1.定义实例存储属性时显示指定了初始值2.实例存储属性的类型为可选类型3.系统提供的默认构造器为实例存储属性分配初始值4.显式提供的构造器为实例存储属性分配初始值类和结构体的构造器1.Swift只为类提供一个无参数的构造器2.Swift为结构体提供两个构造器:无参数的构造器和初始化所有实例存储属性的构造器可能失败的构造器1.可能失败的构造器: 使用init? 或者init! 关键字进行定义2.在构造器执行体中使用return nil来表示构造器失败3.Swift不允许定义两个相同形参列表的构造器, 即使一个是可能失败的构造器, 一个是普通构造器也不行

构造器的外部形参名

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)print(p1)

取消构造器的外部形参名

class Person {    var name: String?    var gender: String?    var age = 0    // 由于该类中前2个实例存储属性使用了可选类型, 后1个实例存储属性指定了初始值    // 因此该结构体对构造器没有要求, 故此处可随便定义一个带参数的构造器    // 取消构造器参数的外部形参名    init(_ name: String, _ gender: String) {        self.name = name        self.gender = gender    }}// 调用构造器时无需使用外部形参名var p = Person("孙悟空", "男")print(p.name)print(p.gender)print(p.age)

构造器的改值

class User1 {    var maxAge = 100    var name: String    init (maxAge: Int, name: String) {        print(self.maxAge)        self.maxAge = Int.max        print(self.maxAge)        self.name = name        self.maxAge = maxAge    }}var u = User1(maxAge: 120, name: "白骨精")print(u.maxAge)print(u.name)

使用闭包或者函数为属性设置初始值

struct closureInit {    // 使用闭包对test实例存储属性执行初始化    var test: Int = {        var dt = NSDate()        // 定义一个时间字段的旗标, 指定将会获取指定日,月信息        var gregorian = NSCalendar.currentCalendar()        // 获取日月的旗标        var unitFlags = NSCalendarUnit.Month        var unitFlags1 = NSCalendarUnit.Day        var comp = gregorian.component(unitFlags, fromDate: dt)        var comp1 = gregorian.component(unitFlags1, fromDate: dt)        // 获取当前的月份        var month = Int(comp)        // 获取当前的第几日        var day = Int(comp1)        // 得到计算结果        return day - month    }()}var ci = closureInit()print(ci.test)

值类型的构造器重载

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: "HelloWorld", amount: 8000000)print("\(oc1.name) \(oc1.amount)")print("\(oc2.name) \(oc2.amount)")

构造器代理:在定义构造器时, 通过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) {        // name = "临时值" // 这行代码将导致错误        self.init(n, c) // 构造器代理        // 调用构造器代理之后, 即可通过self访问该实例的数学        print("--执行显式指定外部形参名的构造器---\(self.name)")    }    // 定义三个参数的构造器    init(name: String, color: String, weight: Double) {        self.init(name, color) // 构造器代理        self.weight = weight    }}var ap1 = Apple("红富士", "粉红色")print("\(ap1.name) ---> \(ap1.color)")var ap2 = Apple(appleName: "青苹果", appleColor: "青色")print("\(ap2.name) ---> \(ap2.color)")var ap3 = Apple(name: "山东苹果", color: "红色", weight: 0.5)print("\(ap3.name) ---> \(ap3.color)")

可能失败的构造器

struct Cat {    let name: String    init?(name: String) {        // 如果传入的name参数为空字符串, 构造器失败, 返回nil        if name.isEmpty {            return nil        }        self.name = name    }}let c1 = Cat(name: "Kitty")if c1 != nil {    // 创建c1的构造器时init?, 因此程序必须对c1执行强制解析    print("c1的name为:\(c1!.name)")}let c4 = Cat(name: "")print(c4 == nil) // 输出ture, 表明c2为nilenum Season3 {    case Spring, Summer, Autumn, Winter    // 使用init!定义可能失败的构造器, 则该构造器创建的实例可进行隐式解析    init!(name: Character) {        // 根据传入的构造器参数选择相应的枚举成员        switch name {            case "S", "s":            self = .Spring            case "U", "u":            self = .Summer            case "A", "a":            self = .Autumn            case "W", "w":            self = .Winter            // 如果传入其他参数, 构造失败, 返回nil        default:            return nil        }    }}let s1 = Season3(name: "s")if s1 != nil {    print("Season3实例构造成功!")}let s2 = Season3(name: "x")print(s2 == nil)
0 0
原创粉丝点击