swift面向对象基础<三>

接下来就讨论一下可选链,类型属性和类型方法,构造器

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
        }
        
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容