zoukankan      html  css  js  c++  java
  • 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 - 逆变性,父类型可以强转到子类型
  • 相关阅读:
    base64加密后字符串长度
    Mysql如何查字段的长度,Mysql中length()、char_length()的区别
    Java 逆变与协变的名词说明
    Java 泛型在实际开发中的应用
    MySQL自增主键排序问题
    【python基础】怎么实现装饰器?
    【python基础】列表推导式
    【python】爬虫实践项目(一):39问医生
    关于DRF序列化器模型字段参数设置报错AssertionError: May not set both `read_only` and `write_only`
    DRF学习笔记
  • 原文地址:https://www.cnblogs.com/lxlx1798/p/11642938.html
Copyright © 2011-2022 走看看