Swift-27-类的初始化与销毁

Swift的初始化是一个有大量规则的固定过程。初始化是设置类型实例的操作,包括给每个存储属性初始值,以及一些其他准备工作。完成这个过程后,实例就可以使用了。 简单来讲就是类的构造函数,基本语法如下:

注意:初始化不仅只针对类,也对结构体有效。类和结构体通用
在这里插入图片描述

对象初始化函数定义

类的初始化

init是关键字,参数个数0~N个,这个是和Objective-C语言是有点不太一样的。

 class CustomType {init(someValue: SomeType) { //init是关键字,参数个数0~N个// 初始化代码}
}

如果不显示声明初始化函数的话,默认为init(){}。

结构体初始化

默认初始化函数

swift为结构体提供了两种默认的构造函数,一种是空属性的,另一种是全属性的。所以像下面的代码两种调用方式都可以。

//Town.swift
struct Town { //定义了一个名为Town的结构体//定义了两个属性var population = 5422var numberOfStoplights = 4//定义实例方法func printDescription() {print("Population: \(population); number of stop lights: \(numberOfStoplights)")}//定义修改方法,需要添加mutating关键字mutating func changePopulation(by amount: Int) {population += amount}
}

测试代码

var town = Town()
var town = Town(population:10000, numberOfStoplights:10)

自定义初始化函数

如果自定义了构造函数,上述两种默认构造函数就全不能用了。

struct Town {//因为删除了默认值,所以不能和自动类型识别了,需要手动指定属性类型let region: Stringvar numberOfStoplights: Intvar population: Int {didSet(oldPopulation) {print("The population has changed to \(population) from \(oldPopulation).")}}/*下面是自定义的初始化方法,这里的?号表示可失败的初始化方法也可以用!号来代替,也可以不写1.可失败的意思一般用于参数检查,如果检查失败则返回一个nil值。然后在程序调用时也用myTown?这种方式调用,会更安全;2. guard 就是一个关键字,用于确保可以提前返回*/init?(region: String, population: Int, stoplights: Int) {//可失败就体现在这里,参数如果不合适,则直接返回nil(创建失改),这种特性比较好用,在其它语言中一种会用抛异常的方式或工厂的方式来实现。guard population > 0 else {return nil}self.region = regionself.population = populationnumberOfStoplights = stoplights}//初始化方法2:N/A表示空字符串值传入init?(population: Int, stoplights: Int) {self.init(region: "N/A", population: population, stoplights: stoplights)}var townSize: Size {get {precondition(self.population >= 0, "Town cannot have negative population.")switch self.population {case 0...10_000:return Size.smallcase 10_001...100_000:return Size.mediumdefault:return Size.large}}}enum Size {case smallcase mediumcase large}func printDescription() {print("Population: \(population); number of stop lights: \(numberOfStoplights); region: \(region)")}mutating func changePopulation(_ amount: Int) {population += amount}
}

测试调用

var myTown = Town(population: 5, stoplights: 4)
myTown?.printDescription()let ts = myTown?.townSize
print(ts) //Optional(swiftcommandtool.Town.Size.small)

对象初始化

类的初始化需要注意继承的问题,默认时类只会提供一个空的构造函数方法,这是和结构体不一样的地方

  1. 指定初始化方法,用于给类的所有属性设置初始值;程序代码没有任何修饰关键字,可以有多个;
  2. 便捷初始化方法,只是一种标识,一般会委托给指定初始化方法来实现;用关键字convenience修饰,可以有多个;
  3. 类的必需初始化方法,一个类要求其子类必须提供特定的初始化方法;
  4. 反初始化方法,在类的实例销毁时执行内存清理过程;用deinit定义,一个类只能有一个此方法

因为默认的初始化方法必须给所有属性设置初始值,则便捷初始化方法则不需要。

默认初始化方法

类的默认初始化方法也是int(){},与结构体不同,类没有默认的成员初始化方法。这解释了为什么之前要给类设置默认值:这样可以利用自带的空初始化方法。比如:let fredTheZombie = Zombie(),其中的空圆括号表示这是一个默认初始化方法。

自定义构造函数

父类

class Monster {var town: Town?var name: Stringvar victimPool: Int {get {return town?.population ?? 0}set(newVictimPool) {town?.population = newVictimPool}}//自定义的初始化方法, required 表示所有子类都必须实现此构造方法,否则程序会报错required init(town: Town?, monsterName: String) {self.town = townname = monsterName}func terrorizeTown() {if town != nil {print("\(name) is terrorizing a town!")} else {print("\(name) hasn't found a town to terrorize yet...")}}
}

子类

默认情况下子类不会自动继承父类的初始化方法,目的是希望避免子类在不经意间提供了无法为所有属性赋值的初始化方法,但在下列两种场景中子类会继承父类的初始化方法:

  1. 子类没有定义任何自定义的初始化方法;
  2. 如果子类复写了父类所有指定的初始化方法,也会继承父类的所有便捷初始化方法;
class Zombie: Monster {class var spookyNoise: String {return "Brains..."}var walksWithLimp: Boolprivate(set) var isFallingApart: Bool//子类特有的初始化方法init(limp: Bool, fallingApart: Bool, town: Town?, monsterName: String) {walksWithLimp = limpisFallingApart = fallingApartsuper.init(town: town, monsterName: monsterName)}//convenience 关键字用来表示快捷初始化方法convenience init(limp: Bool, fallingApart: Bool) {self.init(limp: limp, fallingApart: fallingApart, town: nil, monsterName: "Fred")if walksWithLimp {print("This zombie has a bad knee.")}}//复写父类的初始化方法,可以省略overrid关键字required init(town: Town?, monsterName: String) {walksWithLimp = falseisFallingApart = falsesuper.init(town: town, monsterName: monsterName) //调用父类构造函数}final override func terrorizeTown() {if !isFallingApart {town?.changePopulation(-10)}}}

程序调用

//调用Zombie指定初始化方法:init(limp: Bool, fallingApart: Bool, town: Town?, monsterName: String) 
//The population has changed to 999995 from 1000005.
//Population: 999995; number of stop lights: 4; region: N/A
var fredTheZombie: Zombie? = Zombie(limp: false, fallingApart: false, town: myTown, monsterName: "Fred")
fredTheZombie?.terrorizeTown()
fredTheZombie?.town?.printDescription()//调用快捷初始化方法:convenience init(limp: Bool, fallingApart: Bool)
//This zombie has a bad knee.
var convenientZombie = Zombie(limp: true, fallingApart: false)//Victim pool: Optional(999995)
//The population has changed to 500 from 999995.
//Victim pool: Optional(500)
print("Victim pool: \(fredTheZombie?.victimPool)")
fredTheZombie?.victimPool = 500
print("Victim pool: \(fredTheZombie?.victimPool)")//调用反初始化方法
//Brains...
//Zombie named Fred is no longer with us.
print(Zombie.spookyNoise)
fredTheZombie = nil

初始化函数参数

初始化的函数参数也和普通函数一样,支持内、外名称加类型这种,也支持一些特殊特性,比如下面的_用法,隐藏外部参数名称。

struct WeightRecordInLBS {let weight: Double//用_来指定init(_ pounds: Double) {weight = pounds}init(kilograms kilos: Double) {weight = kilos * 2.20462} 
}//
let wr = WeightRecordInLBS(185)

对象的销毁(反向初始化)

反初始化(deinitialization)是在类的实例没用之后将其清除出内存的过程。从概念上讲,反初始化就是初始化的反面。只有引用类型可以反初始化,值类型不行。 在Swift中,实例被清除出内存之前会调用反初始化方法。这提供了销毁实例前最后做一些维 护工作的机会。

    deinit {print("Zombie named \(name) is no longer with us.")}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2980752.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【webrtc】Chrome和Firefox在SDP协商过程中,针对localhost的不同处理

内网下chrome端webrtc协商失败 现象 我有一个webrtc服务器在局域网内,使用chrome浏览器访问时,发现webrtc在做媒体协商时失败。 具体表现是,在交换sdp后,ice的状态是oniceconnectionstatechange: failed 但是换成Firefox浏览器…

计算机网络相关知识总结

一、概述 计算机网络可以极大扩展计算机系统的功能机器应用范围,提高可靠性,在为用户提供放方便的同时,减少了整体系统费用,提高性价比。 计算机网络的功能主要有:1. 数据共享;2. 资源共享;3. 管…

前端实现将二进制文件流,并下载为excel文件

目录 一、关于二进制流二、项目实践三、常见问题及解决 一、关于二进制流 含义:二进制流是一种计算机文件格式,它的数据以二进制形式存储,与文本文件不同。 二进制文件可以包含任意类型的数据,例如:图像、音频、视频…

Prompt Engineering,提示工程

什么是提示工程? 提示工程也叫【指令工程】。 Prompt发送给大模型的指令。比如[讲个笑话]、[用Python编个贪吃蛇游戏]、[给男/女朋友写情书]等看起来简单,但上手简单精通难 [Propmpt]是AGI时代的[编程语言][Propmpt]是AGI时代的[软件工程][提示工程]是…

Pytorch常用的函数(八)常见优化器SGD,Adagrad,RMSprop,Adam,AdamW总结

Pytorch常用的函数(八)常见优化器SGD,Adagrad,RMSprop,Adam,AdamW总结 在深度学习中,优化器的目标是通过调整模型的参数,最小化(或最大化)一个损失函数。 优化器使用梯度下降等迭代方法来更新模型的参数,以使损失函数…

C#仿QQ抽屉式窗体的设计方法:创建特殊窗体

目录 1.WindowFromPoint函数 2.GetParent函数 3.实例 (1) 图片集合编辑器 (2)Form1.Designer.cs (3)Form1.cs 4.生成效果 QQ软件对于绝大多数的人来说再熟悉不过了,它以使用方便、界面美…

MySQL创建数据库与表

要求: 1.在本机安装数据库 2.创建一个数据库db_classes 3.创建一行表db_hero 4.将四大名著中的常见人物插入这个英雄表 目录 要求: 过程: 结果: 命令总结: 过程: 1.安装数据库 http://t.csdnimg…

【软件工程】【第一章概述】d1

关键字: 什么是软件、软件危机、软件工程定义、软件生命周期、软件过程、瀑布模型

设计模式学习笔记 - 开源实战四(中):剖析Spring框架中用来支持扩展的设计模式

概述 上篇文章,学习了 Spring 框架背后蕴含的设计思想,比如约定优于配置、低侵入松耦合、模块化轻量级等等。这些设计思想可以借鉴到其他框架开发中,在大的设计层面提高框架的代码质量。 除了上篇文章降到的设计思想,实际上&…

《R语言与农业数据统计分析及建模》学习——ggplot2绘图基础

一、农业科研数据可视化常用图形及用途 1、数据可视化的重要性 通过可视化,我们可以更直观地理解和分析数据的特征和趋势。 2、常用图表类型及其概述 散点图:用于展示两个变量之间的关系,可用于观察数据的分布、趋势和异常值。 折线图&…

[SWPUCTF 2022 新生赛]1z_unserialize

function __destruct()这是类的析构函数。在 PHP 中,析构函数会在对象被销毁时自动调用。 $a($this->lly): 将 $this->lly 的值作为参数传递给 $a 所代表的函数。 由题目可知,实现nss反序列化的同时,会触发__destruct()的魔术方法将l…

【数据结构(邓俊辉)学习笔记】向量03——常规向量

文章目录 0.概述1.元素访问2.置乱器3.判等器与比较器4.无序查找4.1 判等器4.2 顺序查找4.3 实现4.4 复杂度 5. 插入5.1 算法实现5.2 复杂度分析 6. 删除6.1 区间删除6.2 单元删除6.3 复杂度 7. 唯一化7.1 实现7.2 正确性7.3 复杂度 8. 遍历8.1 实现8.2 复杂度 9. 总结 0.概述 …

【树莓派学习】开发环境配置

【树莓派学习】开发环境配置 ​ Raspberry Pi OS作为基于Linux的系统,其默认网络配置在国内的网络环境下容易出现访问慢甚至无法连接等问题,不便于我们的学习,同时,树莓派上C/C的使用需要单独安装WiringPi。本文主要介绍如何更改…

探索开源的容器引擎--------------Docker容器操作

目录 一、Docker 容器操作 1.1容器创建 1.2查看容器的运行状态 1.3启动容器 1.4创建并启动容器 1.4.1当利用 docker run 来创建容器时, Docker 在后台的标准运行过程是: 1.4.2在后台持续运行 docker run 创建的容器 1.4.3创建容器并持续运行容器…

PYTHON用[邻接列表]及[邻接矩阵]来存储无向图

# 图可以根据边的性质进行分类:# 有向图(Directed Graph):在有向图中,边是有方向性的,从一个节点指向另一个节点。这意味着从节点 A 到节点 B 的边与从节点 B 到节点 A 的边可以是不同的,或者根…

parallels desktop19出来了吗?2024最新版本有哪些新功能

Parallels Desktop 19已经发布。以下是关于Parallels Desktop 19的相关信息: 发布时间:Parallels Desktop 19是在近期发布的一款虚拟机软件,具体发布时间为2023年下半年。 功能特点: 针对搭载苹果芯片的Mac进行了优化&#xff0c…

微信小程序webview和小程序通讯

1.背景介绍 1.1需要在小程序嵌入vr页面,同时在vr页面添加操作按钮与小程序进行通信交互 1.2 开发工具:uniapp开发小程序 1.3原型图 功能:.点击体验官带看跳转小程序的体验官带看页面 功能:点击立即咨询唤起小程序弹窗打电话 2.…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之五 简单进行车牌检测和识别

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之五 简单进行车牌检测和识别 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之五 简单进行车牌检测和识别 一、简单介绍 二、简单进行车牌检测和识别实现原理 …

Jmeter之Beanshell详解

一、 Beanshell概念 Beanshell: BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法;BeanShell是一种松散类型的脚本语言(这点和JS类似);BeanShell是用Java写成的,一个小型的、免费的、可以下载的、嵌入式的Java源代码解释器,具有对象脚本语言特性…

[Algorithm][前缀和][模板 一维前缀和][模板 二维前缀和][寻找数组中心下标][除自身以外数组的乘积] + 前缀和原理 + 前缀和模板

目录 0.原理讲解1.[模板]一维前缀和1.题目链接2.模板代码实现 2.[模板]二维前缀和1.题目链接2.算法原理讲解3.模板代码实现 3.寻找数组的中心下标1.题目链接2.算法原理详解3.代码实现 4.除自身以外数组的乘积1.题目链接2.算法原理详解3.代码实现 0.原理讲解 前缀和:…