swift學(xué)習(xí)筆記(二)類和結(jié)構(gòu)體、內(nèi)存管理

六、類與結(jié)構(gòu)體

結(jié)構(gòu)體

swift中結(jié)構(gòu)體和類十分相似,即可定義屬性,又可以定義方法,但不具有繼承的特性。使用struct定義結(jié)構(gòu)體,結(jié)構(gòu)體中聲明變量或者常量作為結(jié)構(gòu)體屬性,可以創(chuàng)建函數(shù)作為結(jié)構(gòu)體的方法,用點(diǎn)語法調(diào)用屬性和方法。

struct Car {

? ? //價(jià)格

? ? var price:NSInteger

? ? //品牌

? ? var brand:String

? ? //油量

? ? var petrol:NSInteger

? ? //提供一個(gè)駕駛方法

? ? mutating func drive(){

? ? ? ? if petrol > 0{

? ? ? ? ? ? petrol -= 1

? ? ? ? ? ? print(petrol)

? ? ? ? }

? ? }

? ? //提供一個(gè)加油方法

? ? mutating func addPetrol(){

? ? ? ? petrol += 10

? ? ? ? print("加了10升油")

? ? }

}

func testStructAndClass(){

? ? var car = Car(price: 300000, brand: "奔馳", petrol: 60)

? ? print("這輛:\(car.brand) 價(jià)格:\(car.price) 油量:\(car.petrol)”)

var car1:Car = car

? ? car1.drive();

? ? print(car.petrol)

? ? print(car1.petrol)

}//打印60 59

類是基本數(shù)據(jù)類型,car1和car是兩塊數(shù)據(jù)。

struct PointStruct {

? ? var x:Double

? ? var y:Double

? ? //結(jié)構(gòu)體中,如果修改值類型的變量需要用mutating關(guān)鍵字修飾

? ? mutating func move(x:Double, y:Double){

? ? ? ? self.x += x

? ? ? ? self.y += y

? ? }

}

2.類

類和結(jié)構(gòu)體在屬性和方法聲明上都一樣,不同的是,結(jié)構(gòu)體中不提供構(gòu)造方法,結(jié)構(gòu)體會(huì)根據(jù)屬性自動(dòng)生成一個(gè)構(gòu)造方法,而類需要開發(fā)者自己提供構(gòu)造方法,在init()構(gòu)造方法中需要完成對(duì)類屬性的賦值操作。

class ClassCar{

? ? //價(jià)格

? ? var price:NSInteger

? ? //品牌

? ? var brand:String

? ? //油量

? ? var petrol:NSInteger

? ? //提供一個(gè)駕駛方法

? ? func drive(){

? ? ? ? if petrol > 0{

? ? ? ? ? ? petrol -= 1

? ? ? ? ? ? print(petrol)

? ? ? ? }

? ? }

? ? //提供一個(gè)加油方法

? ? func addPetrol(){

? ? ? ? petrol += 10

? ? ? ? print("加了10升油")

? ? }

? ? //類比結(jié)構(gòu)體多了個(gè)構(gòu)造方法

? ? init(price:NSInteger, brand:String, petrol:NSInteger) {

? ? ? ? self.price = price

? ? ? ? self.brand = brand

? ? ? ? self.petrol = petrol

? ? }

}

類是引用類型,對(duì)類實(shí)例進(jìn)行數(shù)據(jù)傳遞時(shí)不會(huì)產(chǎn)生復(fù)制行為。

? ? var car3:ClassCar = ClassCar.init(price: 300000, brand: "寶馬", petrol: 55)

? ? var car4:ClassCar = car3

? ? car3.drive();

? ? print(car3.petrol)

? ? print(car4.petrol)

? ? //打印54 car3 car4指向同一個(gè)對(duì)象

3.類的繼承

子類繼承父類如果要重寫父類的方法,用關(guān)鍵字override,可以調(diào)用父類的此方法。

class BMWCar: ClassCar {

? ? override func drive() {

? ? ? ? super.drive()

? ? ? ? petrol -= 1

? ? }

? ? override init(price:NSInteger, brand:String="寶馬", petrol:NSInteger) {

? ? ? ? super.init(price: price, brand: brand, petrol: petrol)

? ? }

}

關(guān)鍵字final修飾不可被重寫的屬性或者方法。

? ? final func addPetrol(){

? ? ? ? petrol += 10

? ? ? ? print("加了10升油")

? ? }

4.容器的實(shí)現(xiàn)

swift中Array,String,Dictionary,Set都是采用結(jié)構(gòu)體實(shí)現(xiàn)的,這點(diǎn)和oc有很大區(qū)別,因此上述實(shí)例在數(shù)據(jù)傳遞時(shí)會(huì)發(fā)生復(fù)制,深拷貝。

? ? var arr1:Array = [0,1,2]

? ? var arr2:Array = arr1

? ? arr1.append(3)

? ? print(arr1)

? ? print(arr2)

? ? //打印

[0, 1, 2, 3]

? ? [0, 1, 2]

5.屬性初值

可以在屬性聲明時(shí)提供一個(gè)初值

class BMWCar: ClassCar {

? ? var color: String = "藍(lán)色"

}

6.延時(shí)存儲(chǔ)屬性(懶加載屬性)

延時(shí)存儲(chǔ)屬性用lazy修飾,類構(gòu)造時(shí)候,延時(shí)存儲(chǔ)屬性并不進(jìn)行構(gòu)造初始化,只有當(dāng)開發(fā)者調(diào)用到類實(shí)例的這個(gè)屬性時(shí),此屬性才完成構(gòu)造或者初始化,延時(shí)存儲(chǔ)屬性可以減少類實(shí)例的構(gòu)造時(shí)間。

class Wheel{

? ? var name:String

? ? var bar:Float

? ? init(name:String, bar:Float) {

? ? ? ? self.name = name

? ? ? ? self.bar = bar

? ? }

}

class ClassCar{

? ? lazy var wheel:Wheel = Wheel(name: "左前輪", bar: 2.5)

}

延時(shí)構(gòu)造屬性不是線程安全的,如果在多個(gè)線程中對(duì)延時(shí)存儲(chǔ)屬性進(jìn)行調(diào)用,不能保證只被構(gòu)造一次。

7.get、set方法

class RectClass {

? ? var width:Float

? ? var height:Float

? ? var area:Float{

? ? ? ? get{//定義面積長(zhǎng)x寬

? ? ? ? ? ? return width*height

? ? ? ? }

? ? ? ? set{//計(jì)算寬度=面積/高? newValue是set方法固定值

? ? ? ? ? ? width = newValue/height

? ? ? ? }

? ? }

? ? init(width:Float, height:Float) {

? ? ? ? self.width = width

? ? ? ? self.height = height

? ? }

}

? ? var rect:RectClass = RectClass.init(width: 5, height: 10)

? ? print(rect.width, rect.height, rect.area)

? ? rect.area = 100

? ? print(rect.width, rect.height, rect.area)

? ? //輸出5.0 10.0 50.0

? ? //10.0 10.0 100.0

8.屬性監(jiān)聽器

進(jìn)行屬性初始化時(shí),無論通過構(gòu)造方法設(shè)置屬性或者通過屬性設(shè)置默認(rèn)值都不會(huì)調(diào)用屬性監(jiān)聽器的方法,初始化之后第二次為屬性賦值開始,屬性監(jiān)聽器才會(huì)被調(diào)用。

class RectClass {

? ? var width:Float{

? ? ? ? willSet{

? ? ? ? ? ? print("將要設(shè)置的值:\(newValue)")

? ? ? ? }

? ? ? ? didSet{

? ? ? ? ? ? print("舊的值:\(oldValue)")

? ? ? ? }

? ? }

? ? var height:Float

? ? var area:Float{

? ? ? ? get{//定義面積長(zhǎng)x寬

? ? ? ? ? ? return width*height

? ? ? ? }

? ? ? ? set{//計(jì)算寬度=面積/高? newValue是set方法固定值

? ? ? ? ? ? width = newValue/height

? ? ? ? }

? ? }

? ? init(width:Float, height:Float) {

? ? ? ? self.width = width

? ? ? ? self.height = height

? ? }

}

? ? //初始化時(shí)候width是5

? ? var rect:RectClass = RectClass.init(width: 5, height: 10)

? ? print(rect.width, rect.height, rect.area)

? ? //間接調(diào)用了width的set,新值為10

? ? rect.area = 100

? ? print(rect.width, rect.height, rect.area)

? ? //輸出將要設(shè)置的值:10.0

? ? //舊的值:5.0

? ? //10.0 10.0 100.0

只有存儲(chǔ)屬性可以設(shè)置屬性監(jiān)聽器(width、height),而計(jì)算屬性不能設(shè)置屬性監(jiān)聽。

9.類屬性與類方法

類屬性由static或者class關(guān)鍵字聲明,如果希望子類可以對(duì)計(jì)算方法可以重寫,需要用class關(guān)鍵字聲明。

static定義的類方法也不能被子類重寫,class定義的類方法可以被子類重寫。

class SomeClass{

? ? static var className:String = "class name"

? ? class var subName:String{

? ? ? ? return "sub"+className

? ? }

}

10.下標(biāo)方法

下標(biāo)使用subscript關(guān)鍵字定義,參數(shù)和返回值分別作為下標(biāo)和通過下標(biāo)所取的值,subscript的實(shí)現(xiàn)與計(jì)算屬性類似,必須實(shí)現(xiàn)一個(gè)get,可選實(shí)現(xiàn)set,get用于取值,set用于賦值。

下標(biāo)訪問不局限于一維下標(biāo),可以實(shí)現(xiàn)任意維度的下標(biāo)訪問功能。

class MyArray{

? ? var array:Array<Array<NSInteger>>

? ? init(param:Array<NSInteger>...) {

? ? ? ? array = param

? ? }


? ? subscript(index1:NSInteger, index2:NSInteger)->NSInteger{

? ? ? ? set{

? ? ? ? ? ? array[index1][index2] = newValue

? ? ? ? }

? ? ? ? get{

? ? ? ? ? ? let temp = array[index1]

? ? ? ? ? ? return temp[index2]

? ? ? ? }

? ? }

}

? ? var array = MyArray(param: [1,2,3],[4,5,6],[7,8,9])

? ? print(array[1, 1])

? ? array[1, 1] = 12

? ? print(array[1,1])

? ? //打印5

? ? //12

11.結(jié)構(gòu)體和類在構(gòu)造方法結(jié)束前完成其中存儲(chǔ)屬性的構(gòu)造(延時(shí)存儲(chǔ)屬性除外)。

兩種初始化方法

1.存儲(chǔ)屬性聲明時(shí)直接為其設(shè)置初始默認(rèn)值

2.在構(gòu)造方法里對(duì)存儲(chǔ)屬性構(gòu)造設(shè)默認(rèn)值

如果某個(gè)屬性邏輯上允許為nil,開發(fā)者可以將其聲明為optional可選值類型,對(duì)于optional類型的屬性,如果在構(gòu)造方法中不進(jìn)行賦值,就會(huì)被默認(rèn)賦值為nil。

class Wheel{

? ? var name:String?//如果不進(jìn)行可選值類型的聲明就必須初始化時(shí)候設(shè)默認(rèn)值或者init里面構(gòu)造,否則編譯出錯(cuò)。

? ? var bar:Float

? ? init(name:String, bar:Float) {

//? ? ? ? self.name = name

? ? ? ? self.bar = bar

? ? }

}

如果類或者結(jié)構(gòu)體所有的存儲(chǔ)屬性都有初始默認(rèn)值,開發(fā)者不顯示的提供任何構(gòu)造方法,編譯期也會(huì)默認(rèn)生成一個(gè)無參的構(gòu)造方法init(),在進(jìn)行類型的實(shí)例化時(shí),構(gòu)造出來的實(shí)例所有屬性值都是默認(rèn)的初始值。

class Wheel{

? ? var name:String = "左前輪"

? ? var bar:Float = 2.5

}

11. 指定構(gòu)造方法和便利構(gòu)造方法

構(gòu)造方法分為指定構(gòu)造方法和便利構(gòu)造方法

指定構(gòu)造方法名稱為designated,是基礎(chǔ)構(gòu)造方法,任何類至少有一個(gè)指定構(gòu)造方法。

便利構(gòu)造方法使用convenience關(guān)鍵字來修飾,是為了方便開發(fā)者使用,為類額外添加的構(gòu)造方法。便利構(gòu)造方法最終也要調(diào)用到指定構(gòu)造方法。

原則:

1.子類的指定構(gòu)造方法必須調(diào)用父類的指定構(gòu)造方法

2.便利構(gòu)造方法中必須調(diào)用當(dāng)前類的其它構(gòu)造方法

3.便利構(gòu)造方法最終要調(diào)用到某個(gè)指定構(gòu)造方法

class BaseClass{

? ? init() {指定構(gòu)造方法

? ? ? ? print("指定構(gòu)造方法")

? ? }

? ? convenience init(param:String) {//便利構(gòu)造方法

? ? ? ? print("便利構(gòu)造方法")

? ? ? ? self.init()

? ? }

}

class subClass: BaseClass {

? ? override init() {//指定構(gòu)造方法

? ? ? ? super.init()

? ? }

? ? convenience init(param:String) {//便利構(gòu)造方法

? ? ? ? self.init()

? ? }

? ? convenience init(param:Int) {//便利構(gòu)造方法

? ? ? ? self.init(param:"hhhh")

? ? }

}

12. 構(gòu)造方法的繼承

在繼承關(guān)系中,如果子類沒有重寫任何指定構(gòu)造方法,則默認(rèn)子類會(huì)繼承父類的所有指定構(gòu)造方法,如果子類定義了自己的指定構(gòu)造方法,或者重寫了父類的某個(gè)指定構(gòu)造方法,則子類不再繼承父類的所有指定構(gòu)造方法。

如果子類提供了父類所有的指定構(gòu)造方法(無論是繼承還是重寫),則子類會(huì)默認(rèn)繼承父類的便利構(gòu)造方法。

class BaseClass{

? ? init() {//指定構(gòu)造方法

? ? ? ? print("指定構(gòu)造方法")

? ? }

? ? init(param:Int) {

? ? ? ? print("指定構(gòu)造方法param")

? ? }

? ? convenience init(param:String) {//便利構(gòu)造方法

? ? ? ? print("便利構(gòu)造方法")

? ? ? ? self.init()

? ? }

}

//此類中不進(jìn)行任何構(gòu)造方法的定義,默認(rèn)繼承父類的所有構(gòu)造方法

class subClass1: BaseClass {


}

//對(duì)無參的init指定構(gòu)造方法進(jìn)行重寫,則不再繼承父類的其他構(gòu)造方法

class subClass2: BaseClass {

? ? override init() {

? ? ? ? super.init()

? ? }

}

//沒有重寫父類的構(gòu)造方法,但是重載定義了自己的構(gòu)造方法,則不再繼承父類的其他構(gòu)造方法

class subClass3: BaseClass {

? ? init(param:Bool) {

? ? ? ? super.init()

? ? }

}

//此類中不進(jìn)行任何構(gòu)造方法的定義,默認(rèn)繼承父類的所有構(gòu)造方法

class subClass4: BaseClass {

? ? override init() {

? ? ? ? super.init()

? ? }


? ? override init(param: Int) {

? ? ? ? super.init(param: param)

? ? }

}

13. 構(gòu)造方法的安全性檢查

1.子類的指定構(gòu)造方法中,必須完成當(dāng)前類所有的存儲(chǔ)屬性的構(gòu)造,才能調(diào)用父類的指定構(gòu)造方法,此檢查可以保證:在構(gòu)造完從父類繼承下來的所有存儲(chǔ)屬性前,本身定義的所有屬性也已經(jīng)構(gòu)造完成。

2.子類如果要定義父類中存儲(chǔ)屬性的值,必須在調(diào)用父類構(gòu)造方法之后進(jìn)行設(shè)置,此檢查可以保證:子類在設(shè)置從父類繼承下來的存儲(chǔ)屬性時(shí),此屬性已經(jīng)完成構(gòu)造。

3.如果便利構(gòu)造方法中需要重新設(shè)置某些存儲(chǔ)屬性的值,必須在調(diào)用指定構(gòu)造方法之后進(jìn)行設(shè)置,此檢查可以保證:便利構(gòu)造方法中對(duì)存儲(chǔ)屬性值的設(shè)置不會(huì)被指定的構(gòu)造方法中的設(shè)置覆蓋。

4.子類在調(diào)用父類的構(gòu)造方法之前,不能使用self來引用屬性,此檢查可以保證:使用self調(diào)用實(shí)例本身時(shí),實(shí)例已經(jīng)構(gòu)造完成。

class BaseClassA{

? ? var property:Int


? ? init(param:Int) {

? ? ? ? self.property = param

? ? }

}

class SubClassA: BaseClassA {

? ? var subProperty:Int

? ? init() {

? ? ? ? //檢查原則1:必須在調(diào)用父類構(gòu)造方法前完成本身屬性的賦值

? ? ? ? subProperty = 1

? ? ? ? super.init(param: 0)

? ? ? ? //檢查原則2:如果要重新賦值父類繼承來的某個(gè)屬性,必須在調(diào)用父類的指定構(gòu)造方法后

? ? ? ? property = 2

? ? ? ? //檢查原則4:在完成父類的構(gòu)造方法之后,才能用self關(guān)鍵字

? ? }


? ? convenience init(param1:Int, param2:Int) {

? ? ? ? self.init()

? ? ? ? //檢查原則3:遍歷構(gòu)造方法重要修改屬性的值,必須在調(diào)用指定的構(gòu)造方法之后

? ? ? ? subProperty = param1

? ? ? ? property = param2

? ? }

}

14. 可失敗的構(gòu)造方法與析構(gòu)方法

swift對(duì)于處理某些可能為空的值引入了可選值類型,對(duì)于類的構(gòu)造方法,實(shí)際開發(fā)中可能遇到構(gòu)造失敗的情況,例如需要一些特定的參數(shù),但是參數(shù)不符合要求,構(gòu)造失敗時(shí)返回nil??墒〉臉?gòu)造方法用init?()

class BaseClassA{

? ? var property:Int


? ? init(param:Int) {

? ? ? ? self.property = param

? ? }

? ? //可失敗構(gòu)造方法

? ? init?(param: Bool) {

? ? ? ? guard param else {

? ? ? ? ? ? return nil

? ? ? ? }

? ? ? ? property = 1

? ? }

? ? //析構(gòu)方法

? ? deinit {


? ? }

}

七、內(nèi)存管理

弱引用

class ClassOne{

? ? //用weak進(jìn)行弱引用避免循環(huán)引用

? ? weak var two:ClassTwo?

? ? deinit {

? ? ? ? print("ClassOne deinit")

? ? }

}

class ClassTwo{

? ? var one:ClassOne?

? ? init(one:ClassOne?) {

? ? ? ? self.one = one

? ? }

? ? deinit {

? ? ? ? print("ClassTwo deinit")

? ? }

}

func memoryTest(){

? ? var one:ClassOne? = ClassOne.init()

? ? var two:ClassTwo? = ClassTwo.init(one: one)

? ? one?.two = two

? ? one =nil

? ? two =nil

}

2.無主引用

類似oc的assign,swift提供無主引用,用unowned修飾,被引用對(duì)象釋放時(shí)候引用不會(huì)置nil

class ClassThree{

? ? //無主引用

? ? unowned var four:ClassFour?

? ? deinit {

? ? ? ? print("ClassThree deinit")

? ? }

}


class ClassFour{

? ? var three:ClassThree?

? ? init(three:ClassThree?) {

? ? ? ? self.three = three

? ? }

? ? deinit {

? ? ? ? print("ClassFour deinit")

? ? }

}

? ? var three:ClassThree? = ClassThree.init()

? ? var four:ClassFour? = ClassFour.init(three: three)

? ? three?.four = four

? ? four =nil

? ? three?.four//crash Fatal error: Attempted to read an unowned reference but object 0x6000036a9580 was already deallocated2020-04-09 14:09:46.214608+0800 LearnSwift[53426:10252006] Fatal error: Attempted to read an unowned reference but object 0x6000036a9580 was already deallocated

無主引用與拆包結(jié)合可以使兩個(gè)類的相互引用屬性都是非可選值屬性(非optional),這也是無主引用的最佳場(chǎng)景

class ClassThree{

? ? //無主引用

? ? unowned var four:ClassFour?

? ? init(four:ClassFour) {

? ? ? ? self.four = four

? ? }

? ? deinit {

? ? ? ? print("ClassThree deinit")

? ? }

}

class ClassFour{

? ? //使用隱式拆包

? ? var three:ClassThree!

? ? init() {

? ? ? ? /*在創(chuàng)建three屬性的時(shí)候?qū)?dāng)前類實(shí)例本身作為參數(shù)傳入

? ? ? ? ? 有構(gòu)造方法的原則可知在three屬性創(chuàng)建完成之前,不可以用self屬性

?? ? ? ? 對(duì)于隱式解析類的屬性,上述原則可以忽略,其告訴編譯器默認(rèn)此屬性是構(gòu)造完成的

?? ? ? ? */

? ? ? ? three = ClassThree(four: self)

? ? }

? ? deinit {

? ? ? ? print("ClassFour deinit")

? ? }

}? ?

var? obj5:ClassFour? = ClassFour()

?? ? obj5 = nil

3.block中的循環(huán)引用

class ClassSix{

? ? var name:String = "hhhh"

? ? lazy var close:()->Void = {

? ? ? ? print(self.name)

//self和block產(chǎn)生循環(huán)引用

? ? }

? ? deinit {

? ? ? ? print("ClassSix deinit")

? ? }


}

? ? var obj6:ClassSix? = ClassSix()

? ? obj6?.close()

? ? obj6 =nil

//執(zhí)行完obj6不釋放

class ClassSix{

? ? var name:String = "hhhh"

? ? lazy var close:()->Void = {

? ? ? ? //使用捕獲列表對(duì)block中的self進(jìn)行無主引用的轉(zhuǎn)換

? ? ? ? [unowned self]()->Void in

? ? ? ? print(self.name)

? ? }

? ? deinit {

? ? ? ? print("ClassSix deinit")

? ? }


}

? ? var obj6:ClassSix? = ClassSix()

? ? obj6?.close()

? ? obj6 =nil

//執(zhí)行完obj6可以釋放

3.異常的捕獲

enum MyError:Error {

? ? case DseToryError

? ? case NormarlError

? ? case SimpleError

}

func myFunc(param:Bool) throws -> Void {

? ? if param {

? ? ? ? print("success")

? ? }else{

? ? ? ? throw MyError.NormarlError

? ? }

}

? ? //使用do-catch進(jìn)行異常的捕獲與處理

? ? do {

? ? ? ? try myFunc(param: false)

? ? }catch MyError.SimpleError {

? ? ? ? print("SimpleError")

? ? }catch MyError.NormarlError {

? ? ? ? print("NormarlError")

? ? }catch MyError.DseToryError {

? ? ? ? print("DseToryError")

? ? }catch{

? ? ? ? print("other Error")

? ? }

上述結(jié)構(gòu)可以根據(jù)異常類型進(jìn)行分類處理方案,保證代碼健壯性。

swift還有一種方法,可以將異常映射為optional值,如果函數(shù)沒有異常正常返回,如果執(zhí)行出錯(cuò),拋出異常,則會(huì)返回optional的nil值。使用try?來調(diào)用函數(shù)可以將異常映射為optional值。

? ? let temp = try? myFunc(param: false)

? ? if temp == nil {

? ? ? ? print("執(zhí)行失敗")

? ? }else{

? ? ? ? print("執(zhí)行成功")

? ? }

4.延時(shí)執(zhí)行結(jié)構(gòu)

使用延時(shí)執(zhí)行語句可以保證無論函數(shù)因?yàn)楹畏N原因結(jié)束,在結(jié)束前都會(huì)執(zhí)行延時(shí)執(zhí)行結(jié)構(gòu)塊中的代碼。

func temFun() {

? ? defer {

? ? ? ? print("finish")

? ? }

? ? print("handel")

}

? ? temFun()

? ? //打印handel

? ? //finish

七、類型轉(zhuǎn)換、泛型、擴(kuò)展、協(xié)議

類型檢查

判斷某個(gè)實(shí)例是否屬于某個(gè)類型用關(guān)鍵字is,返回一個(gè)bool值。

? ? var str = "hhh"

? ? if str is String {

? ? ? ? print("str是string類型")

? ? }

類型轉(zhuǎn)換

swift類型轉(zhuǎn)換用as關(guān)鍵字

class MyBaseClass{

? ? var name:String?

}

class MySubClassA: MyBaseClass {

? ? var count:Int?

}

class MySubClassB: MyBaseClass {

? ? var isBiger:Bool?

}

? ? let obj1:MyBaseClass = MyBaseClass()

? ? obj1.name = "hhhhh"

? ? let obj2:MySubClassA = MySubClassA()

? ? obj2.count = 3

? ? let obj3:MySubClassB = MySubClassB()

? ? obj3.isBiger = true

? ? let array:Array<MyBaseClass> = [obj1, obj2, obj3]

? ? for obj in array {

? ? ? ? if obj is MySubClassA {

? ? ? ? ? ? print((obj as! MySubClassA).count!)

? ? ? ? }else if obj is MySubClassB {

? ? ? ? ? ? print((obj as! MySubClassB).isBiger!)

? ? ? ? }else if obj is MyBaseClass {

? ? ? ? ? ? print(obj.name!)

? ? ? ? }

? ? }//打印hhhhh

? ? //3

? ? //true

使用類型轉(zhuǎn)換換時(shí)可以使用as?或者as!。as?是一種安全的轉(zhuǎn)換方式,會(huì)將值類型轉(zhuǎn)后的結(jié)果映射為optional類型,如果類型轉(zhuǎn)換成功,則值為原實(shí)例,如果類型轉(zhuǎn)換失敗,則會(huì)返回nil。

as!是強(qiáng)制轉(zhuǎn)換方式,默認(rèn)轉(zhuǎn)換完成后一定會(huì)成功,如果轉(zhuǎn)換失敗,會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤崩潰。使用as!轉(zhuǎn)換時(shí),必須保證實(shí)例的真實(shí)類型和要轉(zhuǎn)換的類型一致。

Any、AnyObject

AnyObject可以表示通用的對(duì)象類型,不能用來描述值類型。

Any可以表示任何類型,包含值類型和引用類型。

class MySubClassC {


}

class MySubClassD {


}

class MySubClassE {


}

? ? let obj4 = MySubClassC()

? ? let obj5 = MySubClassD()

? ? let obj6 = MySubClassE()

? ? let array2:Array<AnyObject> = [obj4, obj5, obj6]

? ? let array3:Array<Any> = [obj4, obj5, obj6, "hhhh"]

? ? for obj in array3 {

? ? ? ? if obj is MySubClassC {

? ? ? ? ? ? print("MySubClassC")

? ? ? ? }else if obj is MySubClassD{

? ? ? ? ? ? print("MySubClassD")

? ? ? ? }else if obj is MySubClassE{

? ? ? ? ? ? print("MySubClassE")

? ? ? ? }else{

? ? ? ? ? ? print("other")

? ? ? ? }

? ? }

泛型

泛型用來表達(dá)一種未定的數(shù)據(jù)類型,泛型可以作為函數(shù)參數(shù)。參數(shù)列表前用尖括號(hào)定義泛型,如果要定義多個(gè)泛型,用逗號(hào)分隔。作用域是函數(shù)部分。

func exchange<TempType>(param1: inout TempType, param2: inout TempType){

? ? let tmp = param1

? ? param1 = param2

? ? param2 = tmp

}

struct stack<ItemType> {

? ? var items:Array<ItemType> = []

? ? mutating func push(param:ItemType){

? ? ? ? self.items.append(param)

? ? }

? ? mutating func pop()->ItemType{

? ? ? ? return self.items.removeLast()

? ? }

}

擴(kuò)展

特性同oc

class MyBaseClass{

? ? var name:String

? ? var age:NSInteger

? ? init() {

? ? ? ? name = "hhhhh"

? ? ? ? age = 20

? ? }

}

extension MyBaseClass{

? ? var nameAndAge:String{

? ? ? ? return "\(name)\(age)"

? ? }

}

協(xié)議

protocol MyProtocol {

? ? var name:String{get set}

? ? func printName()

? ? static func logClassName()

}

class MyClass12: MyProtocol {

? ? var name: String


? ? init() {

? ? ? ? name = "hhhh"

? ? }

? ? func printName() {

? ? ? ? print(name)

? ? }

? ? static func logClassName() {

? ? ? ? print("MyClass12")

? ? }

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容