第九節(jié)屬性、方法、下標(biāo)、繼承、多態(tài)

一.全局變量

1.內(nèi)存地址的計(jì)算
截屏2020-08-04 上午10.17.20.png

計(jì)算 0xc34f(%rip)的內(nèi)存地 = 下一行的地址(0x100001961 )+ 0xc34f 這里是 16進(jìn)制 = 0x10000DCB0

   class Car {
   //存儲(chǔ)類型屬性,默認(rèn)就是lazy的,只初始化一次,底層使用的是 `dispatch_once`方法
    這里的類型屬性(前面加上static) 本質(zhì)就是 全局變量,只不過前面可以加上訪問權(quán)限控制,放在堆空間,程序運(yùn)行中會(huì)一直存在,直到程序結(jié)束才會(huì)釋放。
  public  static var count = 10
    
}

Car.count = 11;

二.方法(Method)

1. 方法類型
  • 實(shí)例方法:枚舉、結(jié)構(gòu)體、類都可以定義實(shí)例方法
  • 類型方法:通過類型調(diào)用,通過static或是class 關(guān)鍵字定義的方法
struct CarNum {
    
    //類型存儲(chǔ)屬性
    static var num = 10
    
    init(){
        
        CarNum.num = 20
    }
    // 類型方法
    static func getCarNum() -> Int{
        
        print(CarNum.num)
        
        return num
        
    }
    
}

//類型 調(diào)用
CarNum.getCarNum()

  • 類型方法 內(nèi)部 只能訪問類型存儲(chǔ)屬性,不能訪問實(shí)例屬性。

  • 在實(shí)例方法中 self 代表了 調(diào)用的實(shí)例

  • 在類型方法中self代表 類型,print(CarNum.num) = print(self.num) = print(CarNum.self.num)

2.mutating關(guān)鍵字

  • 結(jié)構(gòu)體跟枚舉都是值類型,默認(rèn)情況下 值類型的屬性,不能被自身的實(shí)例方法修改
    截屏2020-08-04 上午11.00.54.png

    會(huì)報(bào)錯(cuò),
    如果自身的實(shí)例方法 想要修改實(shí)例屬性,則要在方法前面加上關(guān)鍵字mutating, 如果是類class 則沒有這個(gè)問題。
截屏2020-08-04 上午11.04.43.png
  • 上面枚舉 是一個(gè)狀態(tài)開關(guān)。三個(gè)狀態(tài)循環(huán)取值

3. 關(guān)鍵字: @discardableResult

*在func 前面加上@discardableResult 可以消除 函數(shù)調(diào)用后返回值未被使用的警告??

截屏2020-08-04 上午11.08.34.png

截屏2020-08-04 上午11.10.26.png

三. 下標(biāo)(subscript)

  • 上標(biāo)在右上角顯示的數(shù)字 下標(biāo) 在右下角顯示的數(shù)字 ,但是在swift 中這里是指 下標(biāo)功能
  • subcript 的語法類似于實(shí)例方法,計(jì)算屬性,本質(zhì)就是方法??梢杂胹ubscript 給任意類型(類、結(jié)構(gòu)體、枚舉)添加下標(biāo)功能
截屏2020-08-04 上午11.22.29.png

給類型 添加 類似于數(shù)組訪問的功能。這里p[0] = 11.1 : 會(huì)調(diào)用set方法,0 賦值給index,11.1賦值給newValue

  • 返回值 double 決定 get方法返回的類型,決定set方法中 賦值的類型(newValue)也是double。
  • subscript 可以接受多個(gè)參數(shù),并且類型任意。
  • subscript 可以沒有set 方法,但是必須要有g(shù)et方法 跟計(jì)算屬性很像。


    截屏2020-08-04 上午11.29.45.png
  • 可以在參數(shù)前面 添加參數(shù)標(biāo)簽
  • 下標(biāo)可以是類型方法,就是前面加上關(guān)鍵字 static或是 class


    截屏2020-08-04 上午11.36.57.png
  • 類型方法 直接通過類型傳遞

當(dāng)類或者結(jié)構(gòu)體 作為下標(biāo)返回值的注意點(diǎn)

1.當(dāng)返回的是 結(jié)構(gòu)體類型時(shí)候
截屏2020-08-04 上午11.42.23.png
  • 這里下標(biāo)是支持這樣樣寫的。
  • 這里 pm[0].x = 11 等價(jià)于 Point(x:11,y:pm[0].y)
2.當(dāng)返回的是 類 時(shí)候
  • 截屏2020-08-04 上午11.48.22.png
  • pm[0] 本質(zhì)返回的是 指針對(duì)象,是可以直接訪問和修改 內(nèi)部的成員變量的。

接受多個(gè)參數(shù)的下標(biāo)

截屏2020-08-04 上午11.52.36.png

四. 繼承

1.在swift中 值類型的(枚舉、結(jié)構(gòu)體)不支持 繼承,只有類支持繼承
  • 沒有父類的類成為 :基類
  • swift 沒有像OC 跟Java一樣規(guī)定 任何類都要繼承自某個(gè)基類
  • 子類可以重寫父類的下標(biāo)、方法、屬性,重寫 必須在前面加上override關(guān)鍵字

2.內(nèi)存結(jié)構(gòu)

  • 內(nèi)存占用
class Dog {

// 前面有 8 個(gè)字節(jié) 存放 指向類型相關(guān)信息,8個(gè)記錄引用計(jì)數(shù)相關(guān)
   var age = 0  //8個(gè)字節(jié)
}
總共占用24個(gè)字節(jié),但是必須是 16的倍數(shù),最后為32字節(jié)
var animus = Dog()
animus.age = 10  //內(nèi)存在堆空間,占用字節(jié)是 16的倍數(shù)。

print(Mems.size(ofRef:anmus)) //32字節(jié)

繼承的內(nèi)存占用情況總結(jié):


截屏2020-08-04 下午2.48.51.png

3.重寫 實(shí)例方法跟下標(biāo)

class Amintion {
    
    func speak() {
        
        print("anmiation Speak")
        
    }
    
    subscript(index : Int) -> Int{
        
        print("\(index)")
        return index
    }
}

var am = Amintion()

//am.speak()
//
//am[10]

class Dog: Amintion {
    
    //重寫父類方法
    override func speak() {
        
        super.speak()
        
    }
    //重寫 下標(biāo)方法
    override subscript(index: Int) -> Int {
        //調(diào)用父類的的下標(biāo) 實(shí)現(xiàn)
        return super[index] + 1
    }
    
}

//父類類型 指向子類對(duì)象,就是多態(tài)
am = Dog()

4.重寫類型方法跟下標(biāo)

  • 被 class 修飾的類型方法、下標(biāo) 允許被子類重寫

  • 被 static 修飾的類型方法、下標(biāo)不允許被子類重寫


    截屏2020-08-04 下午3.26.19.png
  • 父類使用 class 修飾的類型方法,子類是可以使用 static來修飾類型方法的。

5.重寫實(shí)例屬性

  • 子類可以將父類的屬性(存儲(chǔ)或者計(jì)算屬性)重寫為計(jì)算屬性 并且只能重寫為計(jì)算屬性

    截屏2020-08-04 下午3.39.17.png

    重寫后:
    截屏2020-08-04 下午3.47.50.png

  • super.radius相當(dāng)于訪問父類里面的存儲(chǔ)屬性

  • get 方法 里面super.radius相當(dāng)于返回父類的radius

  • super.diameter =相當(dāng)于調(diào)用 父類里面的 set方法

  • super.diameter 相當(dāng)于調(diào)用父類里面的get方法
    打印結(jié)構(gòu):

    截屏2020-08-04 下午3.57.47.png

注意:如果子類的get方法里面訪問radius 不加上super 則會(huì)產(chǎn)生死循環(huán)。這里一定要加上 super關(guān)鍵字進(jìn)行訪問父類的 radius

6.重寫屬性的注意點(diǎn):

  • 子類可以將父類的屬性(存儲(chǔ)或者計(jì)算屬性)重寫為計(jì)算屬性 并且只能重寫為計(jì)算屬性
  • 子類不可以將父類的屬性重寫為存儲(chǔ)屬性
  • 只能重寫 var 屬性,不能重寫 let 屬性
  • 重寫時(shí) 屬性名稱 類型要一致
  • 子類沖洗后的屬性權(quán)限,不能小于父類的屬性權(quán)限,也就是 get 、set 方法的有無


    截屏2020-08-04 下午4.10.48.png

7.重寫類型屬性

截屏2020-08-04 下午4.14.29.png

8.屬性觀察器

  • 可以在子類中為父類屬性(出了只讀計(jì)算屬性、let屬性)添加屬性觀察器


    截屏2020-08-04 下午4.19.47.png
  • 子類里面可以給父類的(實(shí)例或者類型)計(jì)算屬性 增加屬性觀察器,除了let跟只讀計(jì)算屬性。
    截屏2020-08-04 下午4.50.21.png

注意: 訪問 radius 永遠(yuǎn)返貨的是 radius,并且 在最后一句打印時(shí)候,會(huì)先調(diào)用 get radius。第一句的打印 是因?yàn)橐@取 oldValue 的值 打印的 Circle getRadius。

9.final 關(guān)鍵字

  • 被final修飾的 方法、屬性、下標(biāo)禁止被重寫
  • 被final修飾的類 禁止被繼承

swift 多態(tài)的實(shí)現(xiàn)原理

  • 定義: 父類指針 指向子類對(duì)象 又調(diào)用子類方法,就叫多態(tài)
  • OC 多態(tài)的實(shí)現(xiàn)原理 :Runtime
  • C++ 多態(tài):虛表(虛函數(shù)表)
?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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