Swift知识点(三)

11. init、deinit、可选链、协议、元类型

构造和析构

构造方法

构造方法是一种特殊的方法
一个对象创建完毕后,都需要调用构造方法进行初始化(比如属性的初始化)
在这里插入图片描述
验证:init方法是在对象创建完毕的时候调用

回到存储属性
在对象创建的时候,存储属性必须有初始值
两种设置初始值的方法:
在定义属性时为其设置默认值
在构造方法中为属性赋初值

不管在哪赋初值,都是为了保证:对象创建后,存储属性有值

除了没有参数的构造方法,还有自定义的有参数构造方法

构造方法类型

构造方法可以分为两类:
指定构造方法(Designated Constructor)
便利构造方法(Convenience Constructor)
被convenicence修饰的构造方法,被称为便利构造方法
在这里插入图片描述

便利构造器不是必须的,也就是你不用便利构造器也没关系
但是,就比如上述例子,你使用便利构造器,就可以只定义name,而age就不需要重复赋值了,确实是便利

  • 默认情况下,每一个类都有一个隐私的无参的指定构造方法:init(){}
  • 如果一个类定义了一个有参的指定构造方法,就不会自动生成无参的指定构造方法
  • 指定构造方法必须调用其直接父类的指定构造方法(除非没有父类)
  • 便利构造方法必须调用同一类中定义的其他构造方法(不一定是指定构造)
  • 便利构造方法最终必须以调用一个指定构造方法结束

在这里插入图片描述
只有便利构造方法才能直接调用当前类中的其他构造方法
也就是说,指定构造方法在当前类中不能直接调用其他指定构造方法

只有指定构造方法才能直接调用其父类的构造方法
也就是说,便利构造方法不能直接调用其父类的构造方法

  • 如果父类中只有一个指定构造方法且是无参的,那么,子类的指定构造方法默认会自动调用父类中无参的指定构造方法
  • 如果父类中存在有参的指定构造方法,那么,子类的指定构造方法不会自动调用父类的无参的指定构造方法
  • 常量只能在父类中初始化

自动继承

  • 如果子类没有自定义任何指定初始化器,它会自动继承父类所有的指定初始化器

required

  • 用required修饰指定初始化器,表明其所有子类都必须实现该初始化器(通过继承或重写实现)
  • 如果子类重写了required初始化器,也必须加上required,不用加override

可失败初始化器

类、结构体、枚举都可以使用init?定义可失败初始化器
就是,通过这种初始化器初始化的对象,可能是nil,也就是初始化完后的对象,是可选项对象

反初始化器(deinit)

deinit叫做反初始化器,类似C++的析构函数、OC中的dealloc方法
当类的实例对象被释放内存时,就会调用实例对象的deinit方法

deinit{}

  • deinit不接受任何参数,不能写小括号,不能自行调用
  • 父类的deinit被子类继承
  • 子类的deinit实现执行完后,会调用父类的deinit(先子后父)

可选链(Optional Chaining)

  • 如果可选项为nil,调用方法、下标、属性失败,结果为nil
  • 如果可选项不为nil,调用方法、下标、属性成功,结果会被包装成可选项
  • 结果本来就是可选项的,不会进行再次包装

在这里插入图片描述


协议(Protocol)

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

一个简单的协议:

protocol Drawable {
   
   
	//方法
    func draw()
    //属性
    var x: Int {
   
   get set}//可读可写
    var y: Int {
   
   get}//只读
    //下标
    subscript(index: Int) -> Int {
   
   get set}//可读可写
}
  • 协议中定义方法时,不能有默认参数值
  • 默认情况下,协议中定义的内容必须全部实现(也有办法做到只实现一部分协议)

协议中的属性

  • 协议中定义属性时,必须使用var关键字

如果是只读属性(即只有get函数),在实现的时候,是通过函数逻辑动态计算得到的结果,所以返回值是不确定的)

  • 实现协议时的属性权限 >= 协议定义的属性权限
  • 协议定义get、set,用var存储属性或者get、set计算属性去实现
  • 协议定义get,用任何属性都可以实现

协议中static、class使用

为了保证通用,协议中必须使用static定义类型方法、类型属性、类型下标

class关键字只能用在类里面,而结构体也可以遵守协议,结构体没有class,所以,
涉及到类的,协议中只能使用static

在协议声明的时候,声明类型的时候,必须用static,然而,在实现类型的时候,可以用class也可以用static
区别是:
class允许被子类重写;
static不允许被子类重写

protocol Drawable {
   
   
    //声明类方法
    static func draw()
}

class Size: Drawable {
   
   
    //使用class修饰类方法
    class func draw() {
   
   }
}

class Size1: Size {
   
   
    //使用class修饰类方法,允许子类重写
    override class func draw() {
   
   }
}

class Point: Drawable {
   
   
    //使用static修饰类方法
    static func draw() {
   
   
        print("Point-draw")
    }
}

class Point1: Point {
   
   
    //使用static修饰类方法,不允许子类重写
    //Method does not override any method from its superclass
    //override func draw() {}
}

协议中mutating

只有将协议中的实例方法标记为mutating

  • 才允许结构体、枚举的具体实现修改自身内存
  • 类在实现方法时不用加mutating,枚举、结构体才需要加mutating

在这里插入图片描述

协议中init

协议中还可以定义初始化器init
非final类实现时,必须加上required

目的是强制要求遵守协议的类,必须实现init方法

protocol Drawable {
   
   
    init(x: Int, y: Int)
}

class Point: Drawable 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值