美文网首页
Objective-C 泛型 协变 逆变

Objective-C 泛型 协变 逆变

作者: 樂亦leeyii | 来源:发表于2017-09-30 15:37 被阅读0次

    为什么要使用泛型

    在使用NSArray, NSSet, NSDictionary 中都有使用泛型.

    先来看一段没有使用泛型的的代码

    NSMutableArray *arr = [NSMutableArray array];
    
    [arr addObject:@1];
    
    [arr addObject:@"wang"];
    
    [arr addObject:@{}];
    

    在这段代码中可以给数组中添加任意对象, 但是实际情况中我们希望使用数组用来保存同一种类型的变量.

    实际情况中,我们可能希望使用数组保存一组NSString,但是我们操作失误在数组中添加的一个NSNumber使用上面的代码,在编译阶段,Xcode并不会提示错误或给出警告,但是在实际使用中,我们认为这个数组中都是NSString类型的变量,导致对NSNumber使用NSString的方法导致程序crash,显然这样的程序是不健壮的.

    还好使用泛型可以解决这样的问题,代码如下

    image.png

    使用泛型指定数组中的类型为NSString,当我们在数组中添加其他类型时,就会出现提示.

    image.png image.png

    在我们没有指定泛型时,提示显示可以添加id类型

    当我指定泛型时,提示的是在声明过程中与泛型对应的类型.

    使用集合时用泛型声明可以帮助你检查集合中的类型,还能提示集合中应存放的类型.


    如何使用泛型

    我们先看一下NSArray中泛型的使用

    image.png image.png

    通过观察发现,泛型起到的作用就是占位符的作用.

    声明一个数组的指定泛型为NSString *, ObjectType就是一个占位符, 在接口中任何使用ObjectType泛型占位符的时候都会替换为NSString *类型.

    了解了系统泛型使用方法然后自己创建一个ClassStack使用泛型.

    @interface Stack <__covariant T> : NSObject
    
    - (void)push:(T)obj;
    
    - (T)pop;
    
    @end
    

    在声明.h 我们都可以使用泛型T作为占位符.

    image.png

    在类扩展和分类中并不能使用T泛型.

    如果要做分类和类扩展中使用泛型需要重新指定.

    image.png

    在实现中是不能使用泛型的.


    限制泛型

    通常我们在使用泛型时可以代替任意id类型,但有时我们使用泛型时,希望对泛型进行限制,我们希望泛型为UIView类簇中的类型.

    image.png

    很显然这并不是我们希望看到了,所以我们可以对泛型进行限制

    @interface Stack <__covariant T : UIView *> : NSObject
    
    - (void)push:(T)obj;
    
    - (T)pop;
    
    @end
    
    image.png

    使用上面声明方法可以解决问题.

    同时也可以限制泛型遵守指定的协议

    @interface Stack <__covariant T : id<protocol>> : NSObject
    
    - (void)push:(T)obj;
    
    - (T)pop;
    
    @end
    

    协变 逆变

    在上面我们开到了关键字__covariant,下面就来看看这个关键字的作用

    __covariant:协变, 子类转父类 :也就是将子类的指针赋值给父类(多态的延伸)

    __contravariant:逆变 父类转子类:也就是将父类的指针赋值给子类(暂时没有想到有什么作用,如果有哪位大佬知道欢迎指点一二).

    在这里我们创建两个类Animal和他的子类Dog.

    //测试代码
    Stack <Dog *> *stack1 = [Stack new];
    Stack <Animal *> *stack2 = [Stack new];
    stack1 = stack2;
    stack2 = stack1;
    

    接下来我们分别来看看协变和逆变的特性.

    // 逆变 父类指向子类
    @interface Stack <__contravariant T : Animal *> : NSObject
    
    image.png
    // 协变 子类指向父类
    @interface Stack <__covariant T : Animal *> : NSObject
    
    image.png

    相关文章

      网友评论

          本文标题:Objective-C 泛型 协变 逆变

          本文链接:https://www.haomeiwen.com/subject/qttnextx.html