Swfit-02.閉包,屬性,inout,下標,繼承。掩宜。蔫骂。

tree_25.jpg
  • 11. 閉包表達式(Closure Expression) :一種函數(shù)的定義方式
    • 在Swift中,可以通過func定義一個函數(shù)锭亏,也可以通過閉包表達式定義一個函數(shù)
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)

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

輔助理解:

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

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

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

          • 不同于存儲實例屬性,你必須給存儲類型屬性設定初始值昆咽。 因為類型沒有像實例那樣的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
    • 在初始化器中設置屬性值不會觸發(fā)willSet和didSet
    • 在屬性定義時設置初始值也不會觸發(fā)willSet和didSet
    • 父類的屬性在它自己的初始化器中賦值不會觸發(fā)屬性觀察器脏答,但在子類的初始化器中賦值會觸發(fā)屬性觀察器
    • 屬性觀察器糕殉、計算屬性的功能,同樣可以應用在全局變量殖告、局部變量身上
struct Circle {
  var radius: Double {
      willSet {
         print("willSet", newValue)
      } 
      didSet {
            print("didSet", oldValue, radius)  
      }
    } 
    init() {
        self.radius = 1.0
        print("Circle init!")
    }
}
  • 16. inout的本質(zhì)
    • 如果實參有物理內(nèi)存地址阿蝶,且沒有設置屬性觀察器
      • 直接將實參的內(nèi)存地址傳入函數(shù)(實參進行引用傳遞)
    • 如果實參是計算屬性 或者 設置了屬性觀察器
      • 采取了Copy In Copy Out的做法
      • 調(diào)用該函數(shù)時,先復制實參的值黄绩,產(chǎn)生副本【get】
      • 將副本的內(nèi)存地址傳入函數(shù)(副本進行引用傳遞)羡洁,在函數(shù)內(nèi)部可以修改副本的值
      • 函數(shù)返回后,再將副本的值覆蓋實參的值【set】
    • 總結:inout的本質(zhì)就是引用傳遞(地址傳遞)
  • 17. 方法
    • mutating
      結構體和枚舉是值類型爽丹,默認情況下筑煮,值類型的屬性不能被自身的實例方法修改。
      在func關鍵字前加mutating可以允許這種修改行為
    • @discardableResult
      在func前面加個@discardableResult粤蝎,可以消除:函數(shù)調(diào)用后返回值未被使用的警告
      ?
  • 18. 下標(subscript)
    • 使用subscript可以給任意類型(枚舉真仲、結構體、類)增加下標功能初澎,有些地方也翻譯為:下標腳本
    • subscript的語法類似于實例方法秸应、計算屬性,本質(zhì)就是方法(函數(shù))
    • subscript中定義的返回值類型決定了
      get方法的返回值類型
      set方法中newValue的類型
    • subscript可以接受多個參數(shù),并且類型任意
    • subscript可以沒有set方法软啼,但必須要有get方法桑谍。如果只有get方法,可以省略祸挪。
  • 19.繼承(Inheritance)
    • 值類型(枚舉霉囚、結構體)不支持繼承,只有類支持繼承匕积。
    • 沒有父類的類盈罐,稱為:基類
    • Swift并沒有像OC、Java那樣的規(guī)定:任何類最終都要繼承自某個基類
    • 子類可以重寫父類的下標闪唆、方法盅粪、屬性,重寫必須加上override關鍵字
    • 重寫類型方法悄蕾、下標:
      1.被class修飾的類型方法票顾、下標,允許被子類重寫
      2.被static修飾的類型方法帆调、下標奠骄,不允許被子類重寫
    • 重寫屬性:
      • 子類可以將父類的屬性(存儲、計算)重寫為計算屬性
      • 子類不可以將父類屬性重寫為存儲屬性
      • 只能重寫var屬性番刊,不能重寫let屬性
      • 重寫時含鳞,屬性名、類型要一致
      • 子類重寫后的屬性權限 不能小于 父類屬性的權限
        • 如果父類屬性是只讀的芹务,那么子類重寫后的屬性可以是只讀的蝉绷、也可以是可讀寫的
        • 如果父類屬性是可讀寫的,那么子類重寫后的屬性也必須是可讀寫的
    • 重寫類型屬性:
      • 被class修飾的計算類型屬性枣抱,可以被子類重寫
      • 被static修飾的類型屬性(存儲熔吗、計算),不可以被子類重寫
    • 屬性觀察器:
      • 可以在子類中為父類屬性(除了只讀計算屬性佳晶、let屬性)增加屬性觀察器
    • final:
      • 被final修飾的方法桅狠、下標、屬性轿秧,禁止被重寫
      • 被final修飾的類中跌,禁止被繼承
    • 多態(tài)(繼承)原理圖示:


      多態(tài)
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市淤刃,隨后出現(xiàn)的幾起案子晒他,更是在濱河造成了極大的恐慌,老刑警劉巖逸贾,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件陨仅,死亡現(xiàn)場離奇詭異津滞,居然都是意外死亡,警方通過查閱死者的電腦和手機灼伤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門触徐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狐赡,你說我怎么就攤上這事撞鹉。” “怎么了颖侄?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵鸟雏,是天一觀的道長。 經(jīng)常有香客問我览祖,道長孝鹊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任展蒂,我火速辦了婚禮又活,結果婚禮上,老公的妹妹穿的比我還像新娘锰悼。我一直安慰自己柳骄,他們只是感情好,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布箕般。 她就那樣靜靜地躺著耐薯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪隘世。 梳的紋絲不亂的頭發(fā)上可柿,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機與錄音丙者,去河邊找鬼。 笑死营密,一個胖子當著我的面吹牛械媒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播评汰,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼纷捞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了被去?” 一聲冷哼從身側(cè)響起主儡,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎惨缆,沒想到半個月后糜值,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丰捷,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年寂汇,在試婚紗的時候發(fā)現(xiàn)自己被綠了病往。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡骄瓣,死狀恐怖停巷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情榕栏,我是刑警寧澤畔勤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站扒磁,受9級特大地震影響硼被,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜渗磅,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一嚷硫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧始鱼,春花似錦仔掸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至会烙,卻和暖如春负懦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背柏腻。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工纸厉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人五嫂。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓颗品,卻偏偏與公主長得像,于是被迫代替她去往敵國和親沃缘。 傳聞我的和親對象是個殘疾皇子躯枢,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容