美文网首页
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

相关文章

  • Kotlin学习笔记 - 泛型

    1. 基本用法 2. 型变 型变包括 协变、逆变、不变 三种: 协变:泛型类型与实参的继承关系相同 逆变:泛型类型...

  • Scala 通俗易懂 ---- 协变、逆变、不变

    协变、逆变、不变 Scala 语言中协变、逆变、不变是指拥有泛型的类型,在声明和赋值时的对应关系 协变:声明时泛型...

  • 泛型编程中的型变

    在泛型编程中,经常会提到型变。型变分为两种:协变与逆变。协变covariant表示与泛型参数T的变化相同,而逆变c...

  • Scala 泛型协变与泛型边界

    代码准备 泛型协变 泛型协变、逆变、不变是指拥有泛型的类在声明和赋值时的对应关系。 协变:声明时泛型是父类,赋值时...

  • Java协变和逆变

    泛型的协变与逆变 协变与逆变用来描述类型转换(type transformation)后的继承关系,其定义如下:如...

  • JAVA泛型与类型安全

    1. 基础泛型 2. 协变与逆变与不变 协变 简单来说即: Java中的数组是协变的 逆变与协变相对,逆转了类型关...

  • 协变和逆变

    Java的泛型只有通配符?和extends、super,没有语法上的协变和逆变。 什么是协变和逆变? 在混合OO和...

  • Java中的桥接方法与泛型的逆变和协变

    泛型的协变和逆变是什么?对应于Java当中,协变对应的就是,而逆变对应的就是

  • Objective-C 泛型 协变 逆变

    为什么要使用泛型 如何使用泛型 限制泛型 协变 逆变 为什么要使用泛型 在使用NSArray, NSSet, NS...

  • Scala 泛型与补充知识

    一、泛型 1.1不变、协变、逆变 语法 说明协变:Son 是 Father 的子类,则 MyList[Son] 也...

网友评论

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

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