iOS開發之泛型使用


1. 泛型:限制類型

  • 1.1.泛型使用場景:

    • 1.在集合(數組NSArray、字典NSDictionary、集合NSSet)中使用泛型比較常見。

    • 2.當聲明一個類,但是類里面的某些屬性的類型不確定的時候,我們才使用泛型。

  • 1.2.泛型書寫規范

    在類型后面定義泛型:NSMutableArray<UITouch *> dataArray 

  • 1.3.泛型修飾

    只能修飾方法的調用。 

  • 1.4.泛型好處: 

    1.提高開發的規范,減少程序員之間的交流。

    2.通過集合取出來的對象,可以直接當做泛型對象使用。這樣我們就可以直接使用.點語法。

2.代碼使用泛型:

  • 2.1.聲明一個泛型為NSString的數組
    具體做法就是在 NSMutableArray 后帶一個 <NSString *> ,尖括號內部即為泛型類型

    @property (nonatomic, strong, nullable) NSMutableArray<NSString *> *dataArray;
  • 2.2.當我們要給數組添加對象或取出對象的時候,系統就會自動提示應該傳入或者取出來的對象的類型,這個類型就是你剛才聲明的泛型類型
    • 沒有使用泛型
      [self.dataArray addObject:<#(nonnull id)#>];
    • 使用泛型
       [self.dataArray addObject:<#(nonnull NSString *)#>];
    • 添加不正確的類型,會出現警告

       [self.dataArray addObject:@1];
    • 我們可以直接將集合中取出來的對象當做泛型使用

      NSInteger length = [self.dataArray.firstObject length];
    • 代碼如下
       

3.泛型的自定義

  剛才我們只是實現了系統類NSMutableArray的泛型。接下來我們要考慮下,我們怎么樣在我們自己的類中聲明一個泛型的屬性呢?

  為了這個目的,我們創建一個 Language 的類表示 “語言”。並且創建兩個 Language 的子類,分別叫 Java 和 IOS 。很明顯這兩個是“某一個類型的語言”。我們創建一個Person的類,給類聲明一個泛型,在類的 .h 文件中聲明一個聲明一個屬性,這個屬性表示這個人會的語言,即為 IOS 或者 Java 。那么我們有以下兩種聲明方式:  

  • id:任何對象都能傳進來
    @property (nonatomic, strong, null_unspecified) id language;
  •  Language:在外面調用的時候不能提示具體是哪種語言
    @property (nonatomic, strong, null_unspecified) Language *language;
  • 代碼示例:
    #import "Language.h"
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface Person : Language
    /**! 第一種方式*/
    @property (nonatomic,strong,null_unspecified) id languageOne;
    /**! 第二種方式*/
    @property (nonatomic,strong,null_unspecified) Language *languageTwo;
    @end
    
    NS_ASSUME_NONNULL_END

  因為 Language 這個語言並不能代表這個 Person 究竟會什么語言,我們需要的屬性時 IOS 和 Java。這兩種都可以在調用的時候傳入 Java 和 IOS 兩種對象,但它們的缺點也非常明顯,若使用 id 則我們可以傳入任何對象,而不只是 Java 和 IOS ;使用 Language * 呢,我們沒有辦法在編譯的時候確定這個人究竟會什么語言,而只能在運行時判斷。有沒有辦法讓我們在編譯的時候就能知道 Person 具體會哪種 Language 呢?

  辦法就是泛型。

  聲明自定義類的泛型,我們需要做這樣一步:

  • (給類)聲明一個泛型
    @interface JTPerson<ObjectType> : NSObject

    看出區別了嗎?我們在 interface 類名之后加了一對尖括號 <> ,中間是 ObjectType 。這個就代表泛型。這樣我們在聲明屬性的時候就可以這么寫: 

    @property (nonatomic, strong, null_unspecified) ObjectType language;

    也就是,我們現在不指定具體的類型,而在實例化這個類的時候確定這個泛型。若不確定,那么所有的 ObjectType 會自動變成 id 。
    像這樣:

     // iOS
     JTPerson<IOS *> *iOSP = [[JTPerson alloc] init];
     // [iOSP setLanguage:@"123"];
     // [iOSP setLanguage:<#(IOS * _Null_unspecified)#>];
     // [iOSP setLanguage:[[Java alloc] init]];
     // Java
     JTPerson<Java *> *javaP = [[JTPerson alloc] init];
     // [javaP setLanguage:@"123"];
     // [javaP setLanguage:<#(Java * _Null_unspecified)#>];
     // [javaP setLanguage:[[IOS alloc] init]];

    這樣,我們在聲明 Person這個類的時候,就順便聲明了這個類的泛型。這樣系統就會在你使用到泛型的屬性與方法的時候,自動提醒你聲明的泛型類型了。

     

4. 泛型的協變與逆變 

  下圖是系統 NSArray 的頭文件部分,可以看到它使用了自定義泛型並命名為 OBjectType,

  在自定義泛型前加了一個 __covariant 的修飾符,這個修飾符就表示協變性


 

  • __covariant - 協變性,子類型可以強轉到父類型(里氏替換原則)
  • __contravariant - 逆變性,父類型可以強轉到子類型


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM