-
構造函數(shù)
-
構造函數(shù)重載
-
析構函數(shù)
構造函數(shù)
在面向對象的數(shù)據(jù)類型中有一種特殊的函數(shù)或者叫做特殊的方法,它的作用是用于初始化這種類型的數(shù)據(jù)成員,這種函數(shù)或方法我們稱之為構造函數(shù)或構造方法。構造函數(shù)或構造方法其實是一個概念,有些語言習慣叫構造函數(shù),有些語言習慣叫構造方法。
在Swift語言中其實它就是構造器或析構器,我們將構造方法或構造器統(tǒng)一稱為構造函數(shù),將析構器統(tǒng)一稱為析構函數(shù)。
構造函數(shù)概念
結構體和類的實例在構造過程中會調用一種特殊的init方法,稱為構造函數(shù)。構造函數(shù)沒有返回值,可以重載。在多個構造函數(shù)重載的情況下,運行環(huán)境可以根據(jù)它的外部參數(shù)名或參數(shù)列表調用合適的構造函數(shù)。
類似的方法在Objective-C和C++中也稱為構造函數(shù),Java中稱為構造方法。不同的是,Objective-C中的構造函數(shù)有返回值,而C++和Java中的構造函數(shù)名必須與類名相同,沒有返回值。
默認構造函數(shù)
1、類默認構造函數(shù)
注:類中的構造函數(shù)是無參的構造函數(shù)。類中沒有提供構造函數(shù),系統(tǒng)會提供一個沒有參數(shù)的類默認構造函數(shù)
//類默認構造函數(shù)
class Rectangle {
var width: Double = 0.0
var height: Double = 0.0
// init() {
//
// }
}
var rect = Rectangle()//默認有一個無參的構造函數(shù)
rect.width = 320.0
rect.height = 480.0
print("長方形:\(rect.width) x \(rect.height)")
2、結構體的默認構造函數(shù)
注: 與類默認構造函數(shù)相比,結構體默認構造函數(shù)除了有一個無參的構造函數(shù),還多了一個與屬性相對應的構造函數(shù),這些屬性主要是指它的實例存儲屬性,參數(shù)順序與初始化時的順序一致
//結構體默認構造函數(shù)
struct Rectangle2 {
var width: Double = 0.0
var height: Double = 0.0
// init() {
//
// }
// init(width: Double, height: Double) {
// self.width = width
// self.height = height
// }
}
var rect2 = Rectangle() //默認有一個無參的構造函數(shù)
rect2.width = 320.0
rect2.height = 480.0
print("長方形:\(rect2.width) x \(rect2.height)")
//默認有一個有參的構造函數(shù),
//與類默認構造函數(shù)相比,結構體默認構造函數(shù)多一個與屬性相對應的構造函數(shù),
//這些屬性主要是指它的實例存儲屬性
var rectb = Rectangle2(width: 320, height: 480)
注:類或結構體中已經聲明一個構造函數(shù)了,就沒有默認構造函數(shù)的說法了,就沒有默認構造函數(shù)可以使用,只能使用定義和聲明的構造函數(shù)
如下圖:已經聲明了不帶參數(shù)的構造方法init了,所以不存在默認的帶參的構造函數(shù)了,所以報錯

構造函數(shù)與存儲屬性初始化
如果存儲屬性在構造函數(shù)中沒有初始化,在定義的時候也沒有初始化,那么就會發(fā)生編譯錯誤。
計算屬性不保存數(shù)據(jù), 所以不需要初始化
構造函數(shù)也不需要初始化靜態(tài)屬性,因為它們與具體實例個體無關。(構造函數(shù)與個體有關系,它初始化的都是個體屬性,就是我們說的實例屬性,靜態(tài)屬性與個體無關,所以它們不能在構造函數(shù)中初始化)
在構造函數(shù)存儲屬性
class Rectangle4 {
var width: Double
var height: Double
//在構造函數(shù)初始化存儲屬性
init() {
width = 0.0
height = 0.0
}
}
var rect4 = Rectangle()
rect4.width = 320.0
rect4.height = 480.0
print("長方形4:\(rect4.width) x \(rect4.height)")
在構造函數(shù)中不僅可以對變量屬性進行初始化,還可以對常量屬性進行初始化
class Employee {
let no: Int //常量
var name: String?
var job: String?
var salary: Double
var dept: Department?
//在構造函數(shù)中不僅可以對變量屬性進行初始化,還可以對常量屬性進行初始化
init() {
no = 0 //常量在構造函數(shù)中可以被初始化(常量在其他普通方法中是不可以進行初始化的)
salary = 0.0
dept = nil
}
}
struct Department {
let no: Int
var name: String
init() {
no = 10
name = "SALES"
}
}
使用外部參數(shù)名
為了增強程序的可讀性,Swift中的方法和函數(shù)可以使用外部參數(shù)名。構造函數(shù)中也可以使用外部參數(shù)名。構造函數(shù)中的外部參數(shù)名要比一般的方法和函數(shù)更有意義,由于構造函數(shù)命名都是init,如果一個類型中有多個構造函數(shù),我們 可以通過不同的外部參數(shù)名區(qū)分調用不同的構造函數(shù)。
//使用外部參數(shù)名
class RectangleA {
var width: Double
var height: Double
init(W width: Double, H height: Double) {
self.width = width
self.height = height
}
}
var recta = RectangleA(W: 320, H: 480)
print("長方形A:\(recta.width) x \(recta.height)")
注:方法調用時第一個參數(shù)不需要指定外部參數(shù)名,可省略,而構造函數(shù)調用時不能省略第一個參數(shù)的外部參數(shù)名。
局部參數(shù)名可以作為外部參數(shù)名
//局部參數(shù)名可以作為外部參數(shù)名
class RectangleB {
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
}
var rectbb = RectangleB(width: 320, height: 480);
print("長方形B:\(rectbb.width) x \(rectbb.height)")
結構體中使用默認構造函數(shù)
//結構體中使用默認構造函數(shù)
struct RectangleC {
var width: Double = 0.0
var height: Double = 0.0
}
var rectc = RectangleC(width: 320, height: 480)
print("長方形C:\(rectc.width) x \(rectc.height)")
注:這種寫法是一種默認構造函數(shù),但只適用于結構體,在類中不能使用。
構造函數(shù)重載
構造函數(shù)重載有2個條件
1、參數(shù)列表不同
2、外部參數(shù)名不同
以下代碼中有4個構造函數(shù)
class RectangleD {
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
init(W width: Double, H height: Double) {
self.width = width
self.height = height
}
init(length: Double) {
self.width = length
self.height = length
}
init() {
self.width = 640.0
self.height = 940.0
}
}
結構體構造函數(shù)代理
為了減少多個構造函數(shù)間的代碼重復,在定義構造函數(shù)時可以通過調用其他構造函數(shù)來完成實例的部分構造過程,這個過程稱為構造函數(shù)代理
如下面代碼
//結構體構造函數(shù)代理
struct RectangleD {
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
init(W width: Double, H height: Double) {
self.width = width
self.height = height
}
init(length: Double) {
// self.width = length
// self.height = length
self.init(W: length, H: length)
}
init() {
// self.width = 640.0
// self.height = 940.0
self.init(width: 640.0, height: 940.0)
}
}
類構造函數(shù)橫向代理
橫向代理 類似于結構體類型構造函數(shù)代理,發(fā)生在同一類內部,這種構造函數(shù)稱為便利構造函數(shù)(convenience initializer)。
向上代理 發(fā)生在繼承情況下,在子類構造過程中要先調用父類構造函數(shù),初始化父類的存儲屬性,這種構造函數(shù)稱為指定構造函數(shù)(designated initializer)。
//類構造函數(shù)橫向代理
class RectangleE {
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
init(W width: Double, H height: Double) {
self.width = width
self.height = height
}
//使用convenience修飾的構造函數(shù)叫做便利構造函數(shù)
//便利構造函數(shù)通常用在對系統(tǒng)的類進行構造函數(shù)的擴充時使用。
//便利函數(shù)init前面需要加載convenience
//在便利構造函數(shù)中需要明確的調用self.init()
convenience init(length: Double) {
// self.width = length
// self.height = length
self.init(W: length, H: length)
}
convenience init() {
// self.width = 640.0
// self.height = 940.0
self.init(width: 640.0, height: 940.0)
}
}
注:
使用convenience修飾的構造函數(shù)叫做便利構造函數(shù)
便利構造函數(shù)通常用在對系統(tǒng)的類進行構造函數(shù)的擴充時使用
便利函數(shù)init前面需要加載convenience
在便利構造函數(shù)中需要明確的調用self.init()
析構函數(shù)
與構造過程相反,實例最后釋放的時候需要清除一些資源,這個過程就是析構過程。析構過程中也會調用一種特殊的方法 deinit,稱為析構函數(shù)。 析構函數(shù)deinit沒有返回值,也沒有參數(shù),也不需要參數(shù)的小括號,所以不能重載。
注 :
1、在Swift語言中一個類中只能有一個析構函數(shù)
2、析構函數(shù)與構造函數(shù)不同,構造函數(shù)可以在類和結構體中定義
3、析構函數(shù)只能在類中定義使用,結構體和枚舉中是不能定義析構函數(shù)的
提示:
析構函數(shù)只適用與類,不適用于枚舉和結構體。
類似的方法在C++中也稱為析構函數(shù),不同的是, C++中的析構函數(shù)常常用來釋放不再需要的內存資源。而在Swift 中,內存管理采用自動引用計數(shù)(ARC), 不需要析構函數(shù)釋放不需要的實例內存資源,但還是有一些清除工作需要在這里完成,如關閉文件等處理。
class Rectangle {
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
init(W width: Double, H height: Double) {
self.width = width
self.height = height
}
deinit {
print("調用析構函數(shù)");
self.width = 0.0
self.height = 0.0
}
}
var rect1: Rectangle? = Rectangle(width: 320, height: 480)
print("長方形:\(rect1!.width) x \(rect1!.height)")
rect1 = nil
var rect2: Rectangle? = Rectangle(W: 320, H: 480)
print("長方形:\(rect2!.width) x \(rect2!.height)")
rect2 = nil
打印結果如下圖:
