Foundation => Objective-C _ Part3

來源:互聯網
上載者:User

標籤:

1. property
  1. 基本使用 - - - 編譯器只要看到@property, 就會自動產生某一個屬性的getter/setter方法的聲明
2. @synthesize
  1. @synthesize是一個編譯器指令, 它可以簡化我們getter/setter方法的實現
  2. 什麼是實現: 在聲明後面寫上大括弧就代表著實現
  3. 在@synthesize後面告訴編譯器, 需要實現哪個@property產生的聲明
  4. 告訴@synthesize, 需要將傳入的值賦值給誰和返回誰的值給調用者
  5. 如果在@synthesize後面沒有告訴系統將傳入的值賦值給誰, 系統預設會賦值給和@synthesize後面寫得名稱相同的成員變數
3. property的增強:
  1. 預設@property會將傳入的屬性賦值給_開頭的成員變數
  2. @property有一個弊端: 它只會產生最簡單的getter/setter方法的聲明和實現, 並不會對傳入的資料進行過濾
    • 如果想對傳入的資料進行過濾, 那麼我們就必須重寫getter/setter方法
      • 如果重寫了setter方法, 那麼property就只會產生getter方法
      • 如果重寫了getter方法, 那麼property就只會產生setter方法
      • 如果同時重寫了getter/setter方法, 那麼property就不會自動幫我們產生私人的成員變數
    • 如果不想對傳入的資料進行過濾, 僅僅是提供一個方法給外界操作成員變數, 那麼就可以使用@property
  3. 如果利用@property來產生getter/setter方法, 那麼我們可以不寫成員變數, 系統會自動給我們產生一個_開頭的成員變數
  4. 注意: @property自動幫我們產生的成員變數是一個私人的成員變數, 也就是說是在.m檔案中產生的, 而不是在.h檔案中產生的
    • property的修飾符
    • 如果給一個屬性同時提供了getter/setter方法, 那麼我們稱這個屬性為可讀可寫屬性(readwrite — 預設就是這個)
    • 如果只提供了getter方法, 那麼我們稱這個屬性為唯讀屬性(readonly)
    • 如果只提供了setter方法, 那麼我們稱這個屬性為唯寫屬性(readonly)
    • 如果既沒有提供getter也沒有提供setter方法, 那麼我們稱這個屬性為私人屬性
    • 程式員之間有一個約定, 一般情況下擷取BOOL類型的屬性的值, 我們都會將擷取的方法名稱改為isXXX
      • @property(getter=isMarried) BOOL married; // 是否已婚
      • 這麼寫, married的getter方法名, 就是isMarried
      • 同理, 也可以用setter=方法名, 把setter的方法名也重寫了
5. id (動態資料類型)
  1. id是一個資料類型, 並且是一個動態資料類型
    • 既然是資料類型, 所以就可以用來
      • 定義變數
      • 作為函數的參數
      • 作為函數的傳回值
  2. 預設情況下所有的資料類型都是待用資料類型
    • 待用資料類型的特點:
      • 在編譯時間就知道變數的類型,
      • 知道變數中有哪些屬性和方法
      • 在編譯的時候就可以訪問這些屬性和方法,
      • 並且如果是通過待用資料類型定義變數, 如果訪問了不屬於待用資料類型的屬性和方法, 那麼編譯器就會報錯
  3. 動態資料類型的特點:
    • 在編譯的時候編譯器並不知道變數的真實類型, 只有在啟動並執行時候才知道它的真實類型
    • 並且如果通過動態資料類型定義變數, 如果訪問了不屬於動態資料類型的屬性和方法, 編譯器不會報錯
  4. id == NSObject * 萬能指標
    • id和NSObject *的區別:
    • NSObject *是一個待用資料類型
    • id 是一個動態資料類型
  5. 通過待用資料類型定義變數, 不能調用子類特有的方法
    • 通過動態資料類型定義變數, 可以調用子類特有的方法
    • 通過動態資料類型定義的變數, 可以調用私人方法
    • 弊端: 由於動態資料類型可以調用任意方法, 所以有可能調用到不屬於自己的方法, 而編譯時間又不會報錯, 所以可能導致運行時的錯誤
    • 應用情境: 多態, 可以減少代碼量, 避免調用子類特有的方法需要強制類型轉換
    • 為了避免動態資料類型引發的運行時的錯誤, 一般情況下如果使用動態資料類型定義一個變數, 在調用這個對象的方法之前會進行一次判斷, 判斷當前對象是否能夠調用這個方法
           id obj = [Student new];            /*                if ([obj isKindOfClass:[Student class]]) {            // isKindOfClass , 判斷指定的對象是否是某一個類, 或者是某一個類的子類             [obj eat];             }             */           if ([obj isMemberOfClass:[Student class]]) {            // isMemberOfClass : 判斷指定的對象是否是當前指定的類的執行個體            [obj eat];            }    
6. new方法實現原理
  1. new做了三件事情
    • 開闢儲存空間 + alloc 方法
    • 初始化所有的屬性(成員變數) - init 方法
    • 返回對象的地址
  2. 樣本
    // alloc做了什麼事情: 1.開闢儲存空間 2.將所有的屬性設定為0 3.返回當前執行個體對象的地址    Person *p1 = [Person alloc];    // 1.初始化成員變數, 但是預設情況下init的實現是什麼都沒有做 2.返回初始化後的執行個體對象地址    Person *p2 =  [p1 init];    // [[Person alloc] init];    // 注意: alloc返回的地址, 和init返回的地址是同一個地址    NSLog(@"p1 = %p, p2 = %p", p1, p2);
7. 構造方法基本概念
  1. 在OC中init開頭的方法, 我們稱之為構造方法
    • 構造方法的用途: 用於初始化一個對象, 讓某個對象一建立出來就擁有某些屬性和值
  2. 重寫init方法, 在init方法中初始化成員變數
    • 注意: 重寫init方法必須按照蘋果規定的格式重寫, 如果不按照規定會引發一些未知的錯誤
    • 必須先初始化父類, 再初始化子類
    • 必須判斷父類是否初始化成功, 只有父類初始化成功才能繼續初始化子類
    • 返回當前對象的地址
    • 一定要將[super init]的傳回值賦值給self
8. instancetype和id的區別
  1. instancetype == id == 萬能指標 == 指向一個對象

    • id在編譯的時候不能判斷對象的真實類型
    • instancetype在編譯的時候可以判斷對象的真實類型
  2. id和instancetype除了一個在編譯時間不知道真實類型, 一個在編譯時間知道真實類型以外, 還有一個區別

    • id可以用來定義變數, 可以作為傳回值, 可以作為形參
    • instancetype只能用於作為傳回值
  3. 注意: 以後但凡自訂構造方法, 傳回值盡量使用instancetype, 不要使用id

9. 自訂構造方法
  • 自訂構造方法:
  • 其實就是自訂一個init方法
    • 一定是對象方法
    • 一定返回id/instancetype
    • 方法名稱一定以init開頭
    - (instancetype)initWithAge:(int)age;
  • 一個類可以有0個或者多個自訂構造方法
  • 自訂構造方法可以有1個或多個參數
    - (instancetype)initWithAge:(int)age andName:(NSString *)name;
  • 自訂構造方法在繼承中的表現
    • 注意: 自己的事情自己做 ( 屬性是在哪個類裡定義的, 就應該由這個類始終負責賦值 )
    • 自訂構造方法init的順序: 子類init => 父類init => NSObject的 init => NSObject的return => 父類的return => 子類的return
    • 注意: 屬性名稱, 不要以new開頭, 有可能引發未知錯誤 ; 方法名也不要以new開頭
11. 類Factory 方法的基本概念
  1. 什麼是類Factory 方法:
    • 用於快速建立對象的類方法, 我們稱之為類Factory 方法
    • 類Factory 方法中主要用於 給對象分配儲存空間和初始化這Block Storage空間
  2. 規範:
    • 一定是類方法 +
    • 方法名稱以類的名稱開頭, 首字母小寫
    • 一定有傳回值, 傳回值是id/instancetype
  3. 自訂類Factory 方法是蘋果的一個規範, 一般情況下, 我們會給一個類提供自訂構造方法和自訂類Factory 方法用於建立一個對象
  4. 類Factory 方法在繼承中的注意點
    • 注意: 但凡自訂類Factory 方法, 在類Factory 方法中建立對象, 一定要用self來建立
    • self在類方法就代表類對象, 到底代表哪個類對象?? 誰調用當前方法, self就代表誰
13. 類的本質
  1. 所有類的”類對象”的繼承關係就是”元類對象”的繼承關係
  2. 每個對象都有isa,
    • 執行個體對象isa => 類對象
    • 類對象isa => 元類對象
    • 元類對象isa => 根元類對象
    • 根元類對象isa => 根元類對象(指向它自己) 根元類對象, 就是NSObject
14.類對象的擷取和使用情境
  1. 如何擷取類對象
    • 文法: Class test = [類名 class];
    • 注意: 一個類在記憶體中只有一分類對象
  2. 類對象的應用情境
    • 用於建立執行個體對象
    • 用於調用類方法
15.類的啟動過程
  • 只要程式啟動, 就會將類的代碼載入到記憶體中. 放到代碼區
  • load方法會在當前類被載入到記憶體的時候調用, 有且僅會調用一次
    • 如果存在繼承關係, 會先調用父類的load方法, 再調用子類的load方法
    + (void) load {}
  • initialize方法在當前類第一次被使用的時候就會調用(建立類對象的時候)
    • initialize方法在整個程式的運行過程中只會被調用一次, 無論你使用多少次這個類都只會調用一次
    • initialize用於對某一個類進行一次性的初始化
    + (void) initialize { }
16. SEL類型
  • SEL類型的第一個作用, 配合對象/類來檢查對象/類中有沒有實現某一個方法
    • respondToSelector 判斷某個對象有沒有實現規定的方法 (會根據調用對象自動識別對象方法和類方法)
    SEL sel = @selector(setAge:);    Person *p = [Person new];    // 判斷p對象中有沒有實現-號開頭的setAge:方法    //如果P對象實現了setAge:方法,那麼就會返回YES    //如果P對象沒有實現setAge:方法,那麼就會返回NO    BOOL flag = [p respondsToSelector:sell];    NSLog(@"flag = %i",flag);    // respondsToSelector注意點: 如果是通過一個對象來調用該方法, 那麼會判斷該對象有沒有實現-號開頭的方法    // 如果是通過類來調用該方法, 那麼會判斷該類有沒有實現+號開頭的方法    SEL sel1 = @selector(test);    flag = [p respondsToSelector:sel1];    NSLog(@"flag = %i",flag);    flag = [Person respondsToSelector:sel1];    NSLog(@"flag = %i",flag);
  • SEL類型的第二個作用, 配合對象/類來調用某一個SEL方法
    • performSelector 只能傳對象, 可以傳0 ~ 2個參數
    SEL sel = @selector(demo);    Person *p = [Person new];    // 調用p對象中sel類型對應的方法    [p performSelector:sel1];    SEL sel1 = @selector(signalWithNumber:);    // withObject: 需要傳遞的參數    // 注意: 如果通過performSelector調用有參數的方法, 那麼參數必須是物件類型    // 也就是說方法的形參必須接受的是一個對象, 因為withObject只能傳遞一個對象    [p performSelector:sel1 withObject:@"13900000001"];    SEL sel2 = @selector(setAge:);    [p performSelector:sel2 withObject:@(5)];    NSLog(@"age = %i",p.age);    // 注意:performSelector最多隻能傳遞2個參數    SEL sel3 = @selector(sendMessageWithNumber:andContent:);    [p performSelector:sel3 withObject:@"13900000001" withObject:@"abcdef"]; 
  • 配合對象將SEL類型作為方法的形參
    Car *c = [Car new];    SEL sel = @selector(run);    Person *p = [Person new];    [p makeObject:c andSel:sel];

Foundation => Objective-C _ Part3

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.