Swift--構造與析構

  • 構造函數(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ù)了,所以報錯

image.png
構造函數(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

打印結果如下圖:


image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容