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

一 、实例的初始化

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

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

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

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

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 语言进阶(十一)--实例的初始化与类的析构,布布扣,bubuko.com

时间: 2025-01-02 09:27:22

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

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

Swift语言的扩展是为一个已经存在的类.结构.枚举类型添加新功能的一种方式,包括为不能存取源代码的那些已经存在的类型添加功能.        扩展类似于Objective-C语言中的类别,与类别不同的是Swift语言的扩展没有名字.        扩展能够为已存在类型:     1)增加计算属性和计算静态属性:     2)定义新的实例方法和类型方法:     3)提... 请转移到此位置继续阅读,谢谢! 苹果新的编程语言 Swift 语言进阶(十四)--扩展 苹果新的编程语言 Swift 语

苹果新的编程语言 Swift 语言进阶(八)--属性

请转移到此位置阅读,谢谢! 苹果新的编程语言 Swift 语言进阶(八)--属性 http://blog.csdn.net/goohong/article/details/32096289 苹果新的编程语言 Swift 语言进阶(八)--属性,布布扣,bubuko.com

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

协议定义了适合某个特定任务或功能需要的方法.属性和其它需求的一个蓝图.协议本身不提供这些需求的实现,它只是描述了一个任务或功能实现的蓝图.       协议与java 语言中的接口定义类似,都是描述了一个实现可以干什么,而本身却不包含任何实现.与接口不同的是swift语言定义的协议可以被一个类.结构.或者枚举采用,来提供协议规定需求的实际实现,而java 语言的接口只能被类实现.   ... 请麻烦转移到此位置阅读,谢谢! 苹果新的编程语言 Swift 语言进阶(十五)--协议 苹果新的编程语言

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

一. 枚举 枚举定义了一种包含一组相关值的公共类型.枚举是Swift中的一种与类类似的类型,具有许多传统类才有的特征,例如计算属性.实例方法,能够通过扩展或协议增强功能等. 1.1 枚举定义 Swift 语言的枚举类型的定义语法如下: enum CompassPoint { case North case South case East case West } 枚举语法以一个关键字enum来标识,enum后面包含一个枚举类型名字,枚举定义全部放到一对大括号中. 在枚举中定义的值称为枚举成员值,用

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

一 基本操作运算 1. 赋值操作 在Swift 中,可以使用赋值操作为一个常量或一个变量赋值,也可以使用多元组一次为多个常量或变量赋值. Swift 的赋值操作与其它语言最大的不同是赋值操作除了能够为变量或常量赋值外本身不能够返回值. 这个特征可以避免某些条件下赋值操作错误地用于相等比较操作. 如在C语言中,if (x = =y) 很容易误写作if (x = y) ,虽然逻辑结果不正确,但C语言的编译器却无法检查出这种情况,而Swift 语言却可以有效避免这种情况发生,因为 在Swift 中if

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

Swift 是苹果开发和提供的供开发IOS 和OS X应用的一门新的语言.Swift语言基于C 和Objective-C语言,除了提供C 和Objective-C语言具有的所有语法功能外,为了编程方便和高效,Swift在语法上作了大量的优化和改进. Swift采用安全编程模式,具有许多先进的强大的功能 ,如动态运行时.编译动态进行类型检查.Closures.下标功能.自动引用计数.选项类型.通用类型和类型编译时推断.类型的扩展和嵌套.协议类型.功能和类型的通用化.操作符的定制和添加. Swift

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

一.字符串( String  )和字符类型(Character) 字符串是一种字符的带次序的收集类型(相当于数组),字符是字符串中的元素. 在Swift 语言中,字符串是编码独立的Unicode字符的组合,并提供相应方法来获取以各种Unicode呈现方式包含的字符. 1. 字符串定义和初始化 Swift 语言使用var或let关键字来定义一个常量字符串(不可修改)或变量字符串(可以修改).  而不是像Object C语言一样定义两种不同的类型. Swift 语言允许使用一个双引号的字符串来初始化

苹果新的编程语言 Swift 语言进阶(十六)--泛化

泛化允许你定义一个宽松.可重用的函数或者类型,使用泛化能够避免代码的重复,也能以更清楚和抽象的方式来表达程序的意图. 泛化是Swift语言提供的强大功能之一,Swift提供的许多标准库都使用了泛化来创建,如Swift提供的数组和词典类型.通过使用泛化,你能使用一个数组和词典来包含和存储任何类型的元素. 1.1 泛化函数 使用Swift语言你能定义一个可以工作于任意类型的泛化函数,从而不必为每种类型都定义一个具有相同功能的函数,这样就可以大大减少代码的重复. 如对一个实现任意类型值交换(swap)

苹果新的编程语言 Swift 语言进阶(六)--函数和闭包

一 .函数 1.1. 函数的定义和调用 函数的定义以func关键字作为前缀,接着是函数名字,接着跟着一个可以带有参数,也可以不带参数的圆括号,接着用-> 指示函数的返回类型.函数执行体用一对大括号{}包围.如下定义了一个函数名为sayHello的函数,该函数包含一个名字为personName,类型为String的输入参数. func sayHello(personName:String) -> String { let greeting ="Hello, " +person