• 全国 [切换]
  • 二维码
    微商筹货

    手机WAP版

    手机也能找商机,信息同步6大终端平台!

    微信小程序

    微信公众号

    当前位置: 首页 » 行业新闻 » 热点新闻 » 正文

    Swift基础语法(九)协议和元类型

    放大字体  缩小字体 发布日期:2020-01-19 20:18:33   浏览次数:1200  发布人:35a6****  IP:101.229.64.***  评论:0
    导读

    Swift基础学习文章汇总本文主要介绍了Swift中协议的使用以及几个常见协议,还有类型判断(is)和强转(as)的使用和元类型主要内容:协议的使用 常见协议 类型判断和强转 元类型1. 协议的使用 协议可以用来定义方法、属性、下标的声明,但是只有声明没有实现。协议可以被枚举、结构体、类遵守(多个协议之间用逗号隔开) 1.1 基本定义 代码: pro

    Swift基础学习文章汇总

    本文主要介绍了Swift中协议的使用以及几个常见协议,还有类型判断(is)和强转(as)的使用和元类型

    主要内容:

    1. 协议的使用
    2. 常见协议
    3. 类型判断和强转
    4. 元类型

    1. 协议的使用

    协议可以用来定义方法、属性、下标的声明,但是只有声明没有实现。协议可以被枚举、结构体、类遵守(多个协议之间用逗号隔开)

    1.1 基本定义

    代码:

    protocol Drawable { func draw() var x: Int { get set } var y: Int { get } subscript(index: Int) -> Int {get set} }

    说明:

    • 协议只能定义,不能有任何的实现
    • 协议中定义方法时不能有默认参数值,因为协议没有任何实现
    • 默认情况下,协议中定义的内容必须全部实现

    1.2 关键字

    static:
    代码:

    //static 可以看到类中可以使用static也可以使用class,struct只能使用static protocol Drawable2 { static func draw() } class Person1 : Drawable2 { class func draw(){ print("Person1 draw") } } class Person2 : Drawable2 { static func draw() { print("Person2 draw") } } struct Person3 : Drawable2 { static func draw() { print("Person3 draw") } } Person1.draw() Person2.draw() Person3.draw()

    说明:

    • 为了保证通用,协议中必须用static定义类型方法、类型属性、类型下标
    • 因为协议可以被枚举、结构体、类遵守,而class只能在类中使用,所以必须使用static
    • 当然遵守该协议的类的该类型方法依然可以使用class

    mutating
    代码:

    //mutating 类本身就可以进行修改,不需要mutating标记,结构体需要使用mutating标记 protocol Drawable3 { mutating func draw() } class Size: Drawable3 { var width: Int = 0 func draw() { width = 10 } } struct Point : Drawable3 { var x: Int = 0 mutating func draw() { x = 10 } }

    说明:

    • 同样,只有将协议中的实例方法标记为mutating才允许结构体在该方法中修改存储属性值

    1.3 属性

    代码:

    protocol Drawable4 { func draw() var x: Int { get set} var y: Int { get } subscript(index: Int) -> Int { get set } } class Person31: Drawable4 { var x: Int = 0 let y: Int = 0 func draw() { print("Person31 draw") } subscript(index: Int) -> Int { set { } get { index } } } class Person32: Drawable4 { var x: Int { get { 0 } set { } } var y: Int { 0 } func draw() { print("Person32 draw") } subscript(index: Int) -> Int { set { } get { index } } }

    说明:

    • 这里的属性并没有说明是存储属性还是计算属性,只是说明可读可写
    • 可读可写的属性,既可以是存储属性,也可以是计算属性
    • 这里对于x和y都有两种实现方式,可能是存储属性可能是计算属性
    • 协议中定义属性时必须用var属性,因为无法预知它是存储属性还是计算属性
    • 实现协议时的属性权限不能小于协议中定义的属性权限,也就是说协议中定义的东西我们必须要实现,在此基础上想要增加实现也是可以的

    1.4 init

    协议中还可以定义初始化器,遵守该协议的类以及子类都必须实现初始化器,所以需要使用required来修饰晒展网是全面到能查展会礼仪的展会网站。

    代码:

    protocol Livable { init(age: Int) } class Person41 { init(age: Int) { print("Person init") } } class Student: Person41, Livable { required override init(age: Int) { super.init(age: age) print("Student init") } } //Person init //Student init let stu = Student.init(age: 10)

    说明:

    • 非final类实现时必须加上required
    • 如果从协议实现的初始化器,刚好是重写了父类的指定初始化器,那么这个初始化必须同时加required、override

    init、init?、init!的区别

    protocol Livable2 { init() init?(age: Int) init?(no: Int) } class Person42: Livable2 { required init() { print("Person42 init") } required init?(age: Int) { print("Person42 init?") } required init!(no: Int) { print("Person42 init!") } } let p1 = Person42.init() let p2 = Person42.init(age: 10) let p3 = Person42.init(no: 100) print(p1.self) print(p2.self) print(p3.self)

    说明:

    1. 协议中定义的init?、init!,可以用init、init?、init!去实现
    2. 协议中定义的init,可以用init、init!来实现

    1.5 协议的继承

    代码:

    protocol Runnable { func run() } protocol Livable : Runnable { func breath() } class Person : Livable { func breath() {} func run() {} }

    1.5 协议的组合

    代码:

    protocol Livable6 {} protocol Runnable6 {} class Person6 {} // 1、接收Person或者其子类的实例 func fn0(obj: Person6) {} // 2、接收遵守Livable协议的实例 func fn1(obj: Livable6) {} // 3、接收同时遵守Livable、Runnable协议的实例 func fn2(obj: Livable6 & Runnable6) {} // 4、接收同时遵守Livable、Runnable协议、并且是Person或者其子类的实例 func fn3(obj: Person6 & Livable6 & Runnable6) {} //5、也可以直接定义一下使用 typealias RealPerson = Person6 & Livable6 & Runnable6 // 接收同时遵守Livable、Runnable协议、并且是Person或者其子类的实例 func fn4(obj: RealPerson) {}

    说明:

    • 协议可以组合起来遵守,和其他语言的差不多
    • 但是要注意写法,遵守协议的实例和类的实例写法是一样的

    2. 常见协议

    2.1 CaseIterable

    代码:

    enum Season : CaseIterable { case spring, summer, autumn, winter } let seasons = Season.allCases print(seasons.count) // 4 for season in seasons { print(season) } // spring summer autumn winter

    说明:

    • 让枚举遵守CaseIterable协议,可以实现遍历枚举值

    2.2 CustomStringConvertible

    代码:

    //CustomStringConvertible ,自定义打印字符串 //CustomDebugStringConvertible,打印debug字符串 class Person : CustomStringConvertible, CustomDebugStringConvertible { var age = 0 var description: String { "person_\(age)" } var debugDescription: String { "debug_person_\(age)" } } var person = Person() print(person) // person_0 debugPrint(person) // debug_person_0

    说明:

    • 遵守CustomStringConvertible、 CustomDebugStringConvertible协议,都可以自定义实例的打印字符串
    • print调用的是CustomStringConvertible协议的description
    • debugPrint、po调用的是CustomDebugStringConvertible协议的debugDescription

    3. 类型判断和强转

    3.1 任意类型认识

    包括Any、AnyObject、AnyClass三种,Any表示任意类型,包括枚举、结构体、类、函数类型。AnyObject表示任意的类,AnyClass表示任意类的类型

    Any实现

    var stu81: Any = 10 stu81 = "Jack" var stu82: AnyObject = person stu82 = Person42() var classType: AnyClass = Person.self

    说明:

    • stu的类型是Any,因此可以是数值、也可以是字符串、也可以是对象
    • AnyObject表示任意的类
    • AnyClass表示任意类的类型

    3.2 类型判断

    代码:

    protocol Runnable9 { func run() } class Person9 { } class Student9 : Person9, Runnable9 { func run() { print("Student run") } func study() { print("Student study") } } //is var stu9: Any = 10 print(stu9 is Int) // true stu9 = "Jack" print(stu9 is String) // true stu9 = Student9() print(stu9 is Person9) // true print(stu9 is Student9) // true print(stu9 is Runnable9) // true

    说明:

    • 可以看到is可以判断一个变量是否属于某个类型
    • is后面可以放协议、父类,编译器也是可以判断的

    3.3 类型强转

    代码:

    //as var stu92: Any = 10 (stu92 as? Student9)?.study() // 返回nil,不会调用study stu92 = Student9() (stu92 as? Student9)?.study() // 解包,Student study (stu92 as! Student9).study() // 自动解包 ,可能会报错 Student study (stu92 as? Runnable9)?.run() // 解包,Student run

    说明:

    • as用来进行类型强转的
    • 如果可以确定这个类型没有nil,那么可以用as
    • 如果强化失败就会返回nil
    • 如果有可能是nil,那么类型是可选项。就需要用as? 和 as!
    • 我们尽量用as?,这样可以避免报错,如果用as!自动解包的话如果是nil就会报错

    4. 元类型

    4.1 元类型的认识

    代码:
    元类型其实就是类的类型

    class Person10 {} class Student10 : Person10 {} var perType: Person10.Type = Person10.self//拿到Person10的类型赋值给perType变量 var stuType: Student10.Type = Student10.self perType = Student10.self//因为是继承关系,所以可以这样赋值 var anyType: AnyObject.Type = Person10.self anyType = Student10.self//任意类型 public typealias AnyClass = AnyObject.Type var anyType2: AnyClass = Person10.self anyType2 = Student10.self var per = Person10() var perType2 = type(of: per) // Person.self print(Person10.self == type(of: per)) // true

    说明:

    1. x.Type属于类类型,X.self是类型指针,类型指针赋值给类类型的
    2. 这里可以看到Person是类,Person.Type是类的类型
    3. 这个type()并不是函数调用
    4. type(of:p)得到的其实就是Person.self。也就是元类型的地址
    5. 因此pType的类型是Person.Type。

    4.2 元类型应用

    这里通过类类型可以同时对类进行处理
    代码:

    //应用 class Animal { required init() {} } class Cat : Animal {} class Dog : Animal {} class Pig : Animal {} func create(_ clses: [Animal.Type]) -> [Animal] { var arr = [Animal]() for cls in clses { arr.append(cls.init()) } return arr } print(create([Cat.self, Dog.self, Pig.self]))

    4.3 Self关键字

    Self表示当前类型,self表示当前对象,需要注意区分
    代码:

    protocol Runnable { func test() -> Self } class Person : Runnable { required init() {} func test() -> Self { type(of: self).init() } } class Student : Person {}

    说明:
    1、因继承关系中都可以使用,必须使用required
    2、返回类型为了在继承中匹配使用Self
    3、type(of: self).init()这种方式也是为了继承中匹配类型

    不推荐电脑端访问(用户少)
    请微信扫一扫,查看完整信息(记得微信收藏)
     
    (文/匿名(若涉版权问题请联系我们核实发布者) / 非法信息举报 / 删稿)
    打赏
    免责声明
    • 
    本文为昵称为 35a6**** 发布的作品,本文仅代表发布者个人观点,本站未对其内容进行核实,请读者仅做参考,如若文中涉及有违公德、触犯法律的内容,一经发现,立即删除,发布者需自行承担相应责任。涉及到版权或其他问题,请及时联系我们154208694@qq.com删除,我们积极做(权利人与发布者之间的调停者)中立处理。郑重说明:不 违规举报 视为放弃权利,本站不承担任何责任!
    有个别老鼠屎以营利为目的遇到侵权情况但不联系本站或自己发布违规信息然后直接向本站索取高额赔偿等情况,本站一概以诈骗报警处理,曾经有1例诈骗分子已经绳之以法,本站本着公平公正的原则,若遇 违规举报 我们100%在3个工作日内处理!
    0 条相关评论
     

    (c)2008-现在 chouhuo.com All Rights Reserved.