一 、实例的初始化

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

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

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

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

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

}

便利初始化方法的语法除了使用convenience关键字来标示外,语法与指派初始化方法相同。

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中,继承是类区别与其它类型(结构.枚举)的基础行为. 1.1 .类的 ...

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

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

  3. 苹果新的编程语言 Swift 语言进阶(一)--综述

    Swift 是苹果开发和提供的供开发IOS 和OS X应用的一门新的语言.Swift语言基于C 和Objective-C语言,除了提供C 和Objective-C语言具有的所有语法功能外,为了编程方便 ...

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

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

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

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

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

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

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

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

  8. 苹果新的编程语言 Swift 语言进阶(二)--基本数据类型

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

  9. 苹果新的编程语言 Swift 语言进阶(五)--控制流

    Swift 语言支持C语言全部的控制语句.包含for  和while循环语句,if和switch条件语句,以及break和continue控制语句等. Swift 语言除了支持以上语句,还添加了一个f ...

随机推荐

  1. C语言如何在两个文件中访问同一个全局变量

    方法一: 不使用头文件. 1.c 中 int var; 2.c 中 extern int var; 方法二: 使用头文件. 1.c 中 int var; 不必添加#include "1.h& ...

  2. Django 表单校验 表单字段设置 自定义表单校验规则

    今天看到了一篇非常好的博文,拿来和大家分享一下. 内容包括了: 用户注册时输入数据的校验 使用widget进行字段设置 实现自定义的校验规则 参考自下面的这篇文章

  3. How to Find the Self Service Related File Location and Versions

     How to Find the Self Service Related File Location and Versions (文档 ID 781385.1) In this Document ...

  4. JQuery实战---窗口效果

    在前面的相关博文中,小编对jquery的相关知识进行了简单的总结,关于jquery的很多小的知识点,都需要我们自己去动手和实践,一行行代码都需要我们自己亲自动手去敲,今天我们继续来学习jquery的相 ...

  5. SpringMVC源码分析--容器初始化(四)FrameworkServlet

    在上一篇博客SpringMVC源码分析--容器初始化(三)HttpServletBean我们介绍了HttpServletBean的init函数,其主要作用是初始化了一下SpringMVC配置文件的地址 ...

  6. Android性能优化之Bitmap的内存优化

    1.BitmapFactory解析Bitmap的原理 BitmapFactory提供的解析Bitmap的静态工厂方法有以下五种: Bitmap decodeFile(...) Bitmap decod ...

  7. java7 新特性 总结版

    Java7语法新特性: 前言,这是大部分的特性,但还有一些没有写进去,比如多核 并行计算的支持加强 fork join 框架:这方面并没有真正写过和了解.也就不写进来了. 1. switch中增加对S ...

  8. 平述factory reset ——从main system到重引导流程

    关于Android或linux的引导流程,网上大都是从开机开始讲述的,或者直接跳过bootloader引导阶段,直接从init进程开始说起.这里我从手机正常运行状态开始,到重启状态以及重启之后的状态略 ...

  9. Java多种方式读文件,追加文件内容,等对文件的各种操作

    一.多种方式读文件内容. 1.按字节读取文件内容 2.按字符读取文件内容 3.按行读取文件内容 4.随机读取文件内容 import java.io.BufferedReader; import jav ...

  10. UIPassValue页面传值 UI_08(下)

    2.从前一个界面到后一个界面 注意:解题思路  葵花宝典:属性传值  第一步:在下一个界面视图控制器的.h文件中定义一个属性  第二步:在push之前将数据存储到属性中  第三步:取出属性中的值让控件 ...