Swfit-02.閉包,屬性,inout,下標,繼承。。。

tree_25.jpg
  • 11. 閉包表達式(Closure Expression) :一種函數的定義方式
    • 在Swift中,可以通過func定義一個函數,也可以通過閉包表達式定義一個函數
func sum(_ v1: Int, _ v2: Int) -> Int { v1 + v2 }

var fn = {
(v1: Int, v2: Int) -> Int in 
   return v1 + v2
}
fn(10, 20)

{
(v1: Int, v2: Int) -> Int in 
   return v1 + v2
}(10, 20)

{
(參數列表) -> 返回值類型 in 函數體代碼
}
  • 12. 閉包
    • 一個函數和它所捕獲的變量\常量環境組合起來,稱為閉包
      1. 一般指定義在函數內部的函數
      2. 一般它捕獲的是外層函數的局部變量\常量
typealias Fn = (Int) -> Int 
func getFn() -> Fn {
    var num = 0
    func plus(_ i: Int) -> Int {
        num += i
        return num 
    }
    return plus
} // 返回的plus和num形成了閉包

輔助理解:

  • 可以把閉包想象成是一個類的實例對象
    • 內存在堆空間
    • 捕獲的局部變量\常量就是對象的成員(存儲屬性)
    • 組成閉包的函數就是類內部定義的方法
class Closure {
    var num = 0
    func plus(_ i: Int) -> Int { num += i
      return num 
    }
}
  • 13. 自動閉包@autoclosure
// 如果第1個數大于0,返回第一個數。否則返回第2個數
func getFirstPositive(_ v1: Int, _ v2: Int) -> Int {
    return v1 > 0 ? v1 : v2
}
getFirstPositive(10, 20) // 10 
getFirstPositive(-2, 20) // 20 
getFirstPositive(0, -4) // -4
// 改成函數類型的參數,可以讓v2延遲加載
func getFirstPositive(_ v1: Int, _ v2: () -> Int) -> Int? {
    return v1 > 0 ? v1 : v2() 
}
getFirstPositive(-4) { 20 }
func getFirstPositive(_ v1: Int, _ v2: @autoclosure () -> Int) -> Int? {
     return v1 > 0 ? v1 : v2()
}
getFirstPositive(-4, 20)
  • @autoclosure 會自動將 20 封裝成閉包 { 20 }
  • @autoclosure 只支持 () -> T 格式的參數
  • @autoclosure 并非只支持最后1個參數
  • 空合并運算符 ?? 使用了 @autoclosure 技術
  • 有@autoclosure、無@autoclosure,構成了函數重載
    為了避免與期望沖突,使用了@autoclosure的地方最好明確注釋清楚:這個值會被推遲執行
  • 14. 屬性
    • 存儲屬性(Stored Property)
      • 類似于成員變量這個概念
      • 存儲在實例的內存中
      • 結構體、類可以定義存儲屬性
      • 枚舉不可以定義存儲屬性
      • 在創建類 或 結構體的實例時,必須為所有的存儲屬性設置一個合適的初始值
        • 可以在初始化器里為存儲屬性設置一個初始值
        • 可以分配一個默認的屬性值作為屬性定義的一部分
      • 延遲存儲屬性(Lazy Stored Property):
        • 使用lazy可以定義一個延遲存儲屬性,在第一次用到屬性的時候才會進行初始化
        • lazy屬性必須是var,不能是let(存儲類型屬性除外)
        • let必須在實例的初始化方法完成之前就擁有值
        • 如果多條線程同時第一次訪問lazy屬性 無法保證屬性只被初始化1次
        • 當結構體包含一個延遲存儲屬性時,只有var才能訪問延遲存儲屬性, 因為延遲屬性初始化時需要改變結構體的內存
    • 計算屬性(Computed Property)
      • 本質就是方法(函數)
      • 不占用實例的內存
      • 枚舉、結構體、類都可以定義計算屬性
      • set傳入的新值默認叫做newValue,也可以自定義
      • 只讀計算屬性:只有get,沒有set(有set,必須有get)
      • 定義計算屬性只能用var,不能用let。let代表常量:值是一成不變的 ,而計算屬性的值是可能發生變化的(即使是只讀計算屬性)
      • 枚舉原始值rawValue的本質是:只讀計算屬性
    • 類型屬性(Type Property):
      • 屬性可以分為:
        • 實例屬性(Instance Property):只能通過實例去訪問

          • 存儲實例屬性(Stored Instance Property):存儲在實例的內存中,每個實例都有1份
          • 計算實例屬性(Computed Instance Property)
        • 類型屬性(Type Property):只能通過類型去訪問

          • 存儲類型屬性(Stored Type Property):整個程序運行過程中,就只有1份內存(類似于全局變量)
          • 計算類型屬性(Computed Type Property)
          • 可以通過static定義類型屬性
          • 如果是類,也可以用關鍵字class
        • ps:類型屬性細節

          • 不同于存儲實例屬性,你必須給存儲類型屬性設定初始值。 因為類型沒有像實例那樣的init初始化器來初始化存儲屬性
          • 存儲類型屬性默認就是lazy,會在第一次使用的時候才初始化。 就算被多個線程同時訪問,保證只會初始化一次。 存儲類型屬性可以是let
          • 枚舉類型也可以定義類型屬性(存儲類型屬性、計算類型屬性)
// 單例模式
public class FileManager {
    public static let shared = FileManager()
    private init() { }
}
public class FileManager {
    public static let shared = {
       // ....
       // ....
       return FileManager()
     }()
    private init() { }
}
  • 15. 屬性觀察器(Property Observer)
    • 可以為非lazy的var存儲屬性設置屬性觀察器
    • willSet會傳遞新值,默認叫newValu
    • didSet會傳遞舊值,默認叫oldValue
    • 在初始化器中設置屬性值不會觸發willSet和didSet
    • 在屬性定義時設置初始值也不會觸發willSet和didSet
    • 父類的屬性在它自己的初始化器中賦值不會觸發屬性觀察器,但在子類的初始化器中賦值會觸發屬性觀察器
    • 屬性觀察器、計算屬性的功能,同樣可以應用在全局變量、局部變量身上
struct Circle {
  var radius: Double {
      willSet {
         print("willSet", newValue)
      } 
      didSet {
            print("didSet", oldValue, radius)  
      }
    } 
    init() {
        self.radius = 1.0
        print("Circle init!")
    }
}
  • 16. inout的本質
    • 如果實參有物理內存地址,且沒有設置屬性觀察器
      • 直接將實參的內存地址傳入函數(實參進行引用傳遞)
    • 如果實參是計算屬性 或者 設置了屬性觀察器
      • 采取了Copy In Copy Out的做法
      • 調用該函數時,先復制實參的值,產生副本【get】
      • 將副本的內存地址傳入函數(副本進行引用傳遞),在函數內部可以修改副本的值
      • 函數返回后,再將副本的值覆蓋實參的值【set】
    • 總結:inout的本質就是引用傳遞(地址傳遞)
  • 17. 方法
    • mutating
      結構體和枚舉是值類型,默認情況下,值類型的屬性不能被自身的實例方法修改。
      在func關鍵字前加mutating可以允許這種修改行為
    • @discardableResult
      在func前面加個@discardableResult,可以消除:函數調用后返回值未被使用的警告
      ?
  • 18. 下標(subscript)
    • 使用subscript可以給任意類型(枚舉、結構體、類)增加下標功能,有些地方也翻譯為:下標腳本
    • subscript的語法類似于實例方法、計算屬性,本質就是方法(函數)
    • subscript中定義的返回值類型決定了
      get方法的返回值類型
      set方法中newValue的類型
    • subscript可以接受多個參數,并且類型任意
    • subscript可以沒有set方法,但必須要有get方法。如果只有get方法,可以省略。
  • 19.繼承(Inheritance)
    • 值類型(枚舉、結構體)不支持繼承,只有類支持繼承。
    • 沒有父類的類,稱為:基類
    • Swift并沒有像OC、Java那樣的規定:任何類最終都要繼承自某個基類
    • 子類可以重寫父類的下標、方法、屬性,重寫必須加上override關鍵字
    • 重寫類型方法、下標:
      1.被class修飾的類型方法、下標,允許被子類重寫
      2.被static修飾的類型方法、下標,不允許被子類重寫
    • 重寫屬性:
      • 子類可以將父類的屬性(存儲、計算)重寫為計算屬性
      • 子類不可以將父類屬性重寫為存儲屬性
      • 只能重寫var屬性,不能重寫let屬性
      • 重寫時,屬性名、類型要一致
      • 子類重寫后的屬性權限 不能小于 父類屬性的權限
        • 如果父類屬性是只讀的,那么子類重寫后的屬性可以是只讀的、也可以是可讀寫的
        • 如果父類屬性是可讀寫的,那么子類重寫后的屬性也必須是可讀寫的
    • 重寫類型屬性:
      • 被class修飾的計算類型屬性,可以被子類重寫
      • 被static修飾的類型屬性(存儲、計算),不可以被子類重寫
    • 屬性觀察器:
      • 可以在子類中為父類屬性(除了只讀計算屬性、let屬性)增加屬性觀察器
    • final:
      • 被final修飾的方法、下標、屬性,禁止被重寫
      • 被final修飾的類,禁止被繼承
    • 多態(繼承)原理圖示:


      多態
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,750評論 2 370

推薦閱讀更多精彩內容