Swift 构造与析构
前言
- 与 OC 一样,Swift 中也存在构造和析构过程。不同的是,OC 中的构造方法和析构方法只是普通的方法,而 Swift 中构造器和析构器是一种特殊的结构。
1、构造器
在 Swift 中,类或者结构体在初始化时必须保证它们中包含的所有属性都被初始化,构造器用来初始化类或者结构体中的属性,在形式上构造器和方法很像,但是它并不是一个方法。
声明构造器不需要
func
关键字。和 OC 类似,在 Swift 中使用
init
表义构在器。在一个类或者结构体中可以有多个构造器,所有的构造器都叫
init
,系统通过重载的特性来判断使用那个构造器。在参数命名上可以使用和属性相同的名称做对应,如果构造器中参数的名称和属性的名称相同,则使用
self
关键字标示属性。在类中 Swift 提供三种构造器来做初始化:指定构造器、便利构造器和可失败构造器。
// 指定构造器 init(参数名1: 参数类型, 参数名2: 参数类型, ...) { statements
}
// 便利构造器 convenience init(参数名1: 参数类型, 参数名2: 参数类型, ...) { statements
}
// 可失败构造器 init?(参数名1: 参数类型, 参数名2: 参数类型, ...) { statements
}
在某些情况下系统会自动生成一个构造器。
- 如果是在某个类中,当类中的所有属性都有初始值,并且类中没有定义构造器时,就会得到一个没有参数的构造器
init()
。 - 如果是在结构体中,当类中的所有属性都有初始值,并且结构体中没有定义构造器时,就会得到一个默认将所有属性作为参数的构造器。
- 如果是在某个类中,当类中的所有属性都有初始值,并且类中没有定义构造器时,就会得到一个没有参数的构造器
使用构造器时注意事项。
- 在任何构造器完成时,必须保证所有的属性都被初始化了,即便可选型属性的值是
nil
,也算它有值。 - 调用类中的方法和属性必须在初始化完成之后才能进行。
- 在任何构造器完成时,必须保证所有的属性都被初始化了,即便可选型属性的值是
在 Swift 中采用继承式初始化方式。
- 父类和子类的构造器进行交互时,是通过各自的指定构造器进行交互的。
- 便捷构造器只关心本类中的其它构造器,而不关心父类或者子类的构造器。
- 如果在构造器前加上
required
关键字,那么这个类的子类就必须实现它的这个构造器。
1.1 指定构造器
指定构造器包含系统自动生成的构造器和除便利构造器及可失败构造器之外的所有构造器,是默认的初始化方法。
指定构造器必须在
init
中调用父类的指定构造器,而不能调用其自身的其它构造器。init(参数名1: 参数类型, 参数名2: 参数类型, ...) { statements
}
如果没有在类中实现任何指定构造器,那么将继承父类中的所有指定构造器。
// 父类 class Transport { var scope = "" init() {} // 无参数指定构造器 init(str: String) { // 有一个参数的指定构造器
self.scope = str
}
}
// 子类 class Car: Transport {
// 没有在类中实现任何指定构造器
}
// 使用 let myCar = Car() // 使用了父类中的无参数构造器
let myNewCar = Car(str: "ludi") // 使用父类中有一个参数的构造器
一旦在子类中创建了自己的指定构造器,将不能再使用父类中的构造器,并且子类中的指定构造器声明中需要调用父类中的某个指定构造器。
// 父类 class Transport { var scope = "" init() {} // 无参数指定构造器 init(str: String) { // 有一个参数的指定构造器
self.scope = str
}
}
// 子类 class Car: Transport { var wheel = "pulisitong" init(scope: String, wheel: String) { // 创建自己的指定构造器 super.init() // 指定构造器必须调用父类的指定构造器 self.scope = scope
self.wheel = wheel
}
}
// 使用 let myCar = Car(scope: "ludi", wheel: "miqilin") // 此时不能使用父类中无参或者有一个参数的构造器
1.2 便利构造器
调用其它构造器的构造器就叫便利构造器。
便利构造器必须调用一个其它的构造器。
便利构造器必须直接或者间接调用指定构造器之后才能访问其它值,它还可以通过调用其它便利构造器来间接调用指定构造器。
如果一个便利构造器想要调用指定构造器,则它必须并且只能调用本类中的指定构造器,而不能调任何父类的构造器。
convenience init(参数名1: 参数类型, 参数名2: 参数类型, ...) { statements
}
如果子类中重写了父类中所有的指定构造器,那么将继承父类中所有的便利构造器。
// 父类 class Transport { var scope = "" init() {} // 无参数指定构造器 init(str: String) { // 有一个参数的指定构造器
self.scope = str
} convenience init(scope: String) { // 便利构造器
self.init(str: scope) // 调用自身类的指定构造器
}
}
// 子类 class Car: Transport { override init() { // 重写父类指定构造器
super.init() // 指定构造器必须调用父类的指定构造器
} override init(str: String) { // 重写父类指定构造器
super.init() // 指定构造器必须调用父类的指定构造器 self.scope = "Car" + str
}
}
// 使用 let myCar = Car(scope: "ludi") // 调用父类的便利构在器
1.3 可失败构造器
有一些初始化方法允许失败,并且返回
nil
。可失败构造器的定义中
init
后面跟着一个?
。init?(参数名1: 参数类型, 参数名2: 参数类型, ...) { statements
}
通常面对这种可失败构造器建议使用
if-let
或guard-let-else
结构,如果初始化成功就执行操作,否则就做其它操作。if-let
结构if let image = UIImage(named: "test") { // 执行与 image 有关的代码 } else { // 执行与 image 无关的代码
}
guard-let-else
结构guard let image = UIImage(named: "test") else { // 执行与 image 无关的代码
} // 执行与 image 有关的代码
1.4 匿名构造器
有些时候某种对象的子类我们只创建一次,没有必要专门写一个构造器。
使用闭包的形式创建一个匿名的构造器,闭包后需要加 (),用来告诉 Swift 需要立刻执行此闭包,否则会把闭包本身作为值赋给了属性。
let button: UIButton = { let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
button.backgroundColor = UIColor.white return button
}()
使用其它对象方法创建一个匿名的构造器。
let someArray = ["1", "2", "3"]
let someString = someArray.joined(separator: ", ") print(someString) // 1, 2, 3
2、析构器
和构造器对应,Swift 还提供了析构器,用于释放对象。
析构器只适用于类。
一个类中只能定义一个析构器。
析构器的定义和构造器很像,使用关键字
deinit
,并且析构器没有参数。deinit() { // 执行析构过程
}
在把对象设置为
nil
时,系统会自动调用析构器。deinit { self.conn.close()
self.conn = nil
}
由于 Swift 中引入了自动引用计数(ARC),因此不需要读者手动管理内存,但在使用一些自己的资源的时候,需要使用析构器。
- 比如我要建立一个数据库访问类,在初始化时打开链接,如果程序退出,连接不释放,资源就会浪费。
值类型没有析构是因为值类型不会出现 “共享”,每个值类型只有一个拥有者。
- 比如某个方法,值类型会在其拥有者被系统回收时一同回收,我们不需要在意值类型的生命周期。
Swift 构造与析构的更多相关文章
- Swift的构造和析构过程
构造过程 Swift的构造过程通过定义构造器来实现. 只是与Objective-C不同的是,Swift的构造器不须要返回值,相同也不须要表明Func. 另外值得提的是,当构造器中为存储型属性赋值时.不 ...
- C++浅析——继承类中构造和析构顺序
先看测试代码,CTEST 继承自CBase,并包含一个CMember成员对象: static int nIndex = 1; class CMember { public: CMember() { p ...
- Effective C++ -----条款09:绝不在构造和析构过程中调用virtual函数
在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class(比起当前执行构造函数和析构函数的那层).
- 【09】绝不在构造和析构过程中调用virtual方法
1.绝不在构造和析构过程中调用virtual方法,为啥? 原因很简单,对于前者,这种情况下,子类专有成分还没有构造,对于后者,子类专有成分已经销毁,因此调用的并不是子类重写的方法,这不是程序员所期望的 ...
- C++不能中断构造函数来拒绝产生对象(在构造和析构中抛出异常)
这是我的感觉,具体需要研究一下- 找到一篇文章:在构造和析构中抛出异常 测试验证在类构造和析构中抛出异常, 是否会调用该类析构. 如果在一个类成员函数中抛异常, 可以进入该类的析构函数. /// @f ...
- STL——空间配置器(构造和析构基本工具)
以STL的运用角度而言,空间配置器是最不需要介绍的东西,它总是隐藏在一切组件(更具体地说是指容器,container)的背后,默默工作,默默付出.但若以STL的实现角度而言,第一个需要介绍的就是空间配 ...
- 魔法方法:构造和析构 - 零基础入门学习Python041
魔法方法:构造和析构 让编程改变世界 Change the world by program 构造和析构 什么是魔法方法呢?我们来系统总结下: - 魔法方法总是被双下划线包围,例如__init__ - ...
- 再探Delphi2010 Class的构造和析构顺序
发了上一篇博客.盒子上有朋友认为Class的构造和析构延迟加载.是在Unit的初始化后调用的Class的构造.在Unit的反初始化前调用的Class的析构函数. 为了证明一下我又做了个试验 unit ...
- Effective C++_笔记_条款09_绝不在构造和析构过程中调用virtual函数
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 为方便采用书上的例子,先提出问题,在说解决方案. 1 问题 1: ...
随机推荐
- 例子:使用Grunt创建一个Node.js类库
创建一个文件夹. 打开命令行或者powershell, 运行npm init,根据提示填入package的信息. 在文件夹中创建index.js文件. /*! * mymongolib * Cop ...
- mysql存储过程,游标实例
CREATE DEFINER=`root`@`%` PROCEDURE `vir`.`task_payment_byonlinedown`()begin declare _mobile varchar ...
- js escape 与php escape
javascript有编码函数escape()和对应的解码函数unescape(),而php中只有个urlencode和urldecode,这个编码和解码函数对encodeURI和encodeURIC ...
- javascript基于原型的语言的特点
一.基于原型的语言的特点 1 只有对象,没有类;对象继承对象,而不是类继承类. 2 “原型对象”是基于原型语言的核心概念.原型对象是新对象的模板,它将自身的属性共享给新对象.一个对象不但可以享有自己 ...
- 微软BI 之SSRS 系列 - 如何实现报表标签的本地化 - 中文和英文的互换
SSRS 中并没有直接提供本地化的配置方式,因此在 SSRS 中实现本地化,比如有英文标题还有可选的中文标题,就需要通过其它的方式来解决. 比如默认是这样的英文标题 - 但是本地中方用户可能比较喜欢看 ...
- Python取得系统进程列表
一.上代码 import psutil for proc in psutil.process_iter(): try: pinfo = proc.as_dict(attrs=['pid', 'name ...
- canvas语法糖
- 获取请求真实ip
/** * Copyright (c) 2011-2014, James Zhan 詹波 (jfinal@126.com). * * Licensed under the Apache License ...
- SQL Server删除log文件
数据库文件太大 SQL Server用的久了,会发现备份文件越来越大,这个其实主要是log文件的增加,删掉log文件就可以了.不过操作之前最好还是有个完整备份的好. 分离数据库 分离数据库,勾选删除链 ...
- 【leetcode】solution in java——Easy5
转载请注明原文地址: 21:Assign Cookies Assume you are an awesome parent and want to give your children some co ...