一 、实例的初始化

         实例的初始化是准备一个类、结构或枚举的实例以便使用的过程。

初始化包含设置一个实例的每个存储属性为一个初始值,以及运行不论什么其他新的实例可以使用之前须要的设置或初始化。

一个类、结构或枚举能定义一个初始化方法来设置它的特性,用来确保它的实例的全部属性都有有效的初始值。

通过调用类、结构或枚举提供的初始化方法来运行实例的初始化过程。

类的实例也能实现一个析构,用来在类的实例释放之前运行不论什么特定的清除过程来释放分配的专有资源。

1 、 初始化方法的定义

初始化方法定义与实例方法的定义形式类似。能够包括參数,也能够不包括參数。

包括參数时也能够为參数指定本地和外部參数名字。

但初始化方法的名字固定使用init,且不返回值。

最简单的初始化方法是不带參数的init方法。

struct Fahrenheit {

var temperature:Double

init() {

temperature =32.0

}

}

var f =Fahrenheit()

以上定义了一个名字为Fahrenheit的结构。包括一个初始化方法init,用来在该结构实例化时为它唯一的存储属性temperature分配一个初始值32.0 。

除了在初始化方法中为实例的属性设置初始值外,还能在属性定义时为其提供一个默认值。

在属性定义时为其提供默认值是更好的初始化属性的方法,一方面语法更加简单,还有一方面还能够依据提供的默认值的类型判断属性的类型,并且还能够更好的利用默认初始化和初始化继承的特点。

以下相同的结构定义。比上面的结构定义语法更简单。

struct Fahrenheit {

var temperature
=32.0

}

你能使用输入參数和可选的属性类型来定义一个或多个定制的初始化方法,多个定制的初始化方法依据每一个初始化方法提供的參数的名称和类型加以区分和被调用。

例如以下样例展示了怎样使用參数为一个结构定义不同的初始化方法,以及实例化时怎样依据初始化方法提供的參数的不同名字来调用对应的初始化方法。

struct Celsius {

var temperatureInCelsius:Double
=0.0

init(fromFahrenheitfahrenheit:Double)
{

temperatureInCelsius = (fahrenheit
-32.0) /1.8

}

init(fromKelvinkelvin:Double)
{

temperatureInCelsius =kelvin
-273.15

}

}

let boilingPointOfWater
=Celsius(fromFahrenheit:212.0)

// boilingPointOfWater.temperatureInCelsius is 100.0

let freezingPointOfWater
=Celsius(fromKelvin:273.15)

因为初始化方法的參数名字和类型扮演的重要角色,因此假设你在一个初始化方法的定义中没有提供一个外部名字,则Swift会自己主动为它的每个參数提供一个自己主动分配的名字,由Swift自己主动产生的外部參数名字与本地參数名字同样。

与实例方法同样,当然假设你不想为初始化方法的參数提供外部參数名字。能够使用’_’作为參数的外部名字。

常量属性的值可以在初始化期间被改动,但对于类的实例的常量属性,仅能在引入该属性的类的初始化方法中改动,而不能被其子类改动。

2、 默认初始化方法

假设一个结构或基类没有提供定制的初始化方法,且其全部的属性都提供有默认值,则Swift可以为其提供一个默认的初始化方法,默认的初始化方法设置新创建的实例的全部属性的值为它们的默认值。例如以下样例所看到的:

class ShoppingListItem
{

var name:String?

var quantity
=1

var purchased
=false

}

var item =ShoppingListItem()

因为类ShoppingListItem的全部的三个属性都提供有默认值。且ShoppingListItem是一个基类,也没有为其提供定制的初始化方法。因此Swift为其提供了一个默认初始化方法,默认初始化方法不带參数。

3、 结构类型的成员逐一初始化方法(memberwise Initializers)

假设一个结构的全部的存储属性都提供有默认值,且未定义不论什么自己的定制初始化方法。则除了能够使用Swift为其提供的默认初始化方法外,也自己主动接收一个成员逐一初始化方法。

成员逐一初始化方法是初始化新结构实例的成员属性的一种快捷方式,新实例的全部属性的初始值通过名字逐一传送给该初始化方法然后被设置。例如以下所看到的:

struct Size
{

var width
=0.0,height =0.0

}

let twoByTwo =Size(width:2.0,height:2.0)

在该样例中,结构Size包括仅有的两个存储属性width和height,并都带有默认值,而其本身也没有提供初始化方法,因此其自己主动接收一个为init(width:height:)的成员逐一初始化方法。

可以使用它来初始化一个新的Size实例。其属性的初始值通过成员逐一初始化方法的參数逐一提供。

对于值类型(结构和枚举)。你能在自定义的初始化方法内部使用self.init调用同样类型的其他初始化方法。

4、 类的初始化

因为类涉及继承,因此一个类的初始化过程比較复杂。须要在初始化过程完毕对类的全部存储属性(包含从它的超类链继承的随意属性)的初始化。Swift为了确保正确完毕一个类的初始化。定义了两类类的初始化方法:指派初始化方法和便利初始化方法。

4.1、 类的指派初始化方法和便利初始化方法

类的指派初始化方法是一个类的主要初始化方法。

一个类的指派初始化方法初始化该类本身引入的全部的属性。然后向上调用其直接超类的初始化方法来继续超类琏的初始化过程。一个类必须有至少一个指派初始化方法。通常一个类仅有一个指派初始化方法。

类的便利初始化方法是类的次要初始化方法。你能为类定义一个便利初始化方法来调用同样类的其他初始化方法。一个类能够不必提供便利初始化方法。

便利初始化方法作为一种便利的初始化方法,主要用来方便创建某些特定的实例或者特定输入值类型的类的实例,因此在便利初始化方法中调用指派初始化方法时,对于指派初始化方法的一些參数被设置为默认值。

类的指派初始化方法和便利初始化方法之间的调用必须遵守例如以下规则:

1)指派初始化方法必须调用它的直接超类的指派初始化方法。

2)便利初始化方法必须调用同样类的另外的能够使用的初始化方法。

3) 便利初始化方法最后必须调用一个指派初始化方法。

类的指派初始化方法语法与值类型的简单初始化方法同样:

init(parameters) {

statements

}

便利初始化方法的语法除了使用conveniencekeyword来标示外,语法与指派初始化方法同样。

convenience init(parameters)
{

statements

}

4.2、 类的两阶段初始化

在Swift中类的初始化分成两个阶段完毕,在第一个阶段,每个存储属性被引入它的类的初始化方法分配一个初始值。一旦每个存储属性的初始状态确定。開始第二个初始化阶段:在新的实例可以使用之前,进一步定制它的存储属性。

为了正确完毕一个类的两阶段初始化过程,Swift进行例如以下安全检查:

1) 指派初始化方法必须在调用它的直接超类的初始化方法之前确保由它的类引入的全部的属性被初始化。

2) 指派初始化方法在为一个继承的属性分配一个值之前必须向上调用它的直接超类的初始化方法;

3) 便利初始化方法必须在为不论什么属性分配值之前调用其他的初始化方法;

4) 一个初始化方法在第一个阶段完毕前不能调用其他不论什么实例方法,读不论什么实例属性的值或者引用self,这是由于这时实例还处于内存不确定状态。

4.3、 初始化方法的继承和重写

与Objective-C语言不同,Swift 中子类默认不继承它的超类的初始化方法。但同意在子类中重写超类的初始化方法。与方法、属性、下标不同。初始化方法的重写不须要写一个override标识。

4.4、 自己主动初始化继承

在一些条件下,超类的初始化方法也能被它的子类自己主动继承。

规则1:假设一个子类未定义不论什么指派初始化方法,则自己主动继承它的超类的全部指派初始化方法。即对于指派初始化方法继承而言,没有则继承。

规则2:假设一个子类提供了其超类的全部指派初始化方法的实现,能够是通过规则1继承来的。也能够是提供自己特定的实现,那么它自己主动继承其超类的全部便利初始化方法。即对于便利初始化方法继承而言假设已实现超类的全部指派初始化方法,则自己主动继承全部便利初始化方法。

5、 使用闭合或功能为属性设置默认值。

       
      你能使用一个闭合或全局功能来为一个存储属性提供特定的默认值。

在该属性所属类型的新的实例被初始化时,为一个属性提供默认值的闭合或全局功能被调用,且返回一个值作为该属性的默认值。

例如以下所看到的:

   class SomeClass
{

let someProperty:SomeType
= {

return someValue

}()

}

              该例使用一个闭合为someProperty属性提供默认值。该闭合以一个圆括号结束。说明该闭合可以被运行。

须要注意:在使用一个闭合为一个属性分配默认值时。由于在闭合运行时,该实例还没有初始化完毕,因此在闭合内部不能存取实例的其他不论什么属性值,即使那些属性带有默认值,也不能使用隐含的self属性。也不能调用不论什么实例的方法。

二、析构

在一个实例不再须要时,Swift会自己主动释放它。

Swift使用automatic reference counting (ARC)来实现一个实例的内存管理。

因此当实例释放时。用户不须要手工清除它所使用的系统资源。

但是当你的实例包括和使用了自己分配的资源时。你可能须要运行一些额外的清除工作。比如创建一个打开一个文件的类。就可能须要在类的实例释放前关闭该文件。

每一个类可以定义至少一个析构。析构语法例如以下:

deinit {

// perform the deinitialization

}

一个实例的析构在实例释放之前自己主动被调用。超类的析构被子类继承,超类的析构可以在子类的析构实现的最后被自己主动调用。

超类的析构总是被调用,即使一个没有提供自己的析构的子类。

在一个实例的析构完毕之前该实例还没有被释放,因此在析构内部可以存取实例的全部属性。

版权所有所有。请明确注明转载的链接和出处,谢谢!

版权声明:本文博客原创文章,博客,未经同意,不得转载。

苹果公司的新的编程语言 Swift 高级语言(十一)--初始化类的析构函数的一个实例的更多相关文章

  1. 苹果公司的新的编程语言 Swift 高级语言()两--基本数据类型

    一  .   常量和变量 Swift语言 对常量和变量的声明进行了明白的区分 Swift语言的常量类型比C 语言的constants类型更加强大,语义更加明白. 常量和变量的差别是常量在设置或初始化后 ...

  2. 苹果公司的新的编程语言 Swift 高级语言(十五)--协议

    协议定义了适合某个特定任务或功能须要的方法.属性和其他需求的一个蓝图.协议本身不提供这些需求的实现,它仅仅是描写叙述了一个任务或功能实现的蓝图. 协议与java 语言中的接口定义类似,都是描写叙述了一 ...

  3. 苹果新的编程语言 Swift 语言进阶(三)--基本运算和扩展运算

    一 基本操作运算 1. 赋值操作 在Swift 中,能够使用赋值操作为一个常量或一个变量赋值,也能够使用多元组一次为多个常量或变量赋值. Swift 的赋值操作与其他语言最大的不同是赋值操作除了可以为 ...

  4. 苹果新的编程语言 Swift 语言进阶(十五)--协议

    协议定义了适合某个特定任务或功能需要的方法.属性和其它需求的一个蓝图.协议本身不提供这些需求的实现,它只是描述了一个任务或功能实现的蓝图. 协议与java 语言中的接口定义类似,都是描述了一个实现可以 ...

  5. 苹果新的编程语言 Swift 语言进阶(十四)--扩展

    扩展是为一个已经存在的类.结构.枚举类型添加新功能的一种方式,包括为不能存取源代码的那些已经存在的类型添加功能. 扩展类似于Objective-C语言中的类别,与类别不同的是Swift语言的扩展没有名 ...

  6. 苹果新的编程语言 Swift 语言进阶(十一)--实例的初始化与类的析构

    一 .实例的初始化          实例的初始化是准备一个类.结构或枚举的实例以便使用的过程.初始化包括设置一个实例的每一个存储属性为一个初始值,以及执行任何其它新的实例能够使用之前需要的设置或初始 ...

  7. 苹果新的编程语言 Swift 语言进阶(九)--方法和下标

    一.方法 方法是与特定类型相关的函数.与属性一样,方法也包括实例方法和类型方法. 类.结构.枚举都能定义实例方法,用来封装或实现给定类型的一个实例相关的功能或特定任务. 类.结构.枚举也能定义与类型本 ...

  8. 苹果新的编程语言 Swift 语言进阶(七)--枚举、结构、类

    Swift语言中,具有类特征的类型包括三种,即枚举类型.结构类型(包括基本类型,基本类型实际都是结构类型的特例).类.其中枚举类型.结构类型是属于值类型,类属于引用类型.三种类型都可以添加属性.方法. ...

  9. 苹果新的编程语言 Swift 语言进阶(四)--字符串和收集类型

    一.字符串( String  )和字符类型(Character) 字符串是一种字符的带次序的收集类型(相当于数组),字符是字符串中的元素. 在Swift 语言中,字符串是编码独立的Unicode字符的 ...

随机推荐

  1. [eclipse] 三个操作技巧

    [eclipse] 三个操作技巧 1.快捷键Ctrl+Shift+i:Debug调试中直接获取方法的返回值 在下图代码中,想知道getHost(),则在调试时运行完该句代码后,选中"urlU ...

  2. 将markdown格式转化为bootstrap风格html

    前言:这些年markdown格式的文件很流行,像github里project说明文档都是用markdown格式编写. 一方面,我们能够通过pandoc将markdown文件转换为html,这样将htm ...

  3. pc机进入android的shell

    一直都知道自己非常死板,刚刚再一次验证了.. 下载下来android开发必备的工具之后,就按部就班的一步步的来了.没想过这些工具有没有其它用处,更有甚者,在刚開始接触android的时候.居然不知道自 ...

  4. NumPy简明教程

    源地址:http://blog.csdn.net/sunny2038/article/details/9002531 http://blog.csdn.net/sunny2038/article/de ...

  5. java基础---->java调用oracle存储过程(转)

    存储过程是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它.今天 ...

  6. 14.3.3 Locks Set by Different SQL Statements in InnoDB 不同的SQL语句在InnoDB里的锁设置

    14.3.3 Locks Set by Different SQL Statements in InnoDB 不同的SQL语句在InnoDB里的锁设置 locking read, 一个UPDATE,或 ...

  7. 飘逸的python - yield简明教程

    发现还有非常多人对yield不理解,云里雾里,于是试着用文字表述. 仅仅要函数含有yield语句,它就返回一个生成器.所以我们与其把其看成函数定义,不如看作是生成器定义.函数用return返回,而生成 ...

  8. 怎么获取Spring的ApplicationContext

    在 WEB 开发中,可能会非常少须要显示的获得 ApplicationContext 来得到由 Spring 进行管理的某些 Bean, 今天我就遇到了,在这里和大家分享一下, WEB 开发中,怎么获 ...

  9. 分布式发布订阅消息系统Kafka

    高吞吐量的分布式发布订阅消息系统Kafka--安装及测试   一.Kafka概述 Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据. 这种动作(网页浏览, ...

  10. java多线程:ReentrantReadWriteLock读写锁使用

    Lock比传统的线程模型synchronized更多的面向对象的方式.锁和生活似,应该是一个对象.两个线程运行的代码片段要实现同步相互排斥的效果.它们必须用同一个Lock对象. 读写锁:分为读锁和写锁 ...