Kotlin学习笔记(四)--kotlin的泛型

一.Java泛型

java中泛型通常用法

List<TextView> textViews = new ArrayList<TextViews>();

List集合中生命泛型的类型

注意,java泛型不适合多态,比如:

//java的多态
TextView textview = new Button(context);

List<Button> buttons = new ArrayList<Button>();
List<TextView> textViews = buttons;
//IDE会报错

ButtonTextView的子类,但是List<Button>不属于List<TextView>的子类,java的泛型在编译的时候会类型擦除,而数组没有问题。比如

//todo
TextView

java提供了泛型通配符? extend,上界通配符,是java泛型具有协变性 Covariance

List<Button> buttons = new ArrayList<Button>();
//使用泛型通配符
List<? extends TextView> textViews = buttons;

extends限制了泛型的上限,正常使用情况

List<? extends TextViews> textViews = new ArrayList<TextVies>();//本身
List<? extends TextViews> textViews = new ArrayList<Button>();//直接子类
List<? extends TextViews> textViews = new ArrayList<RadioButton>();//间接子类

有泛型的List集合,可以正常get元素数据,但是add操作的时候会报错。因此只能向外提供数据,即是生产者Producer.

java中的? super,下界通配符,使java泛型具有逆变性 Contravariance

List<? super Button> buttons = new ArrayList<TextViews>(); 	

正常的使用情况

List<? super Button> buttons = new ArrayList<Button>(); //本身
List<? super Button> buttons = new ArrayList<TextView>(); //直接父类
List<? super Button> buttons = new ArrayList<Object>(); //间接父类

使用下界通配符? super的泛型的get操作,得到的元素只能是Object,而add操作是可以的。这种泛型类型称为消费者Consumer

java泛型总结

1.可以使用泛型通配符 ? extends 来使泛型支持协变,但是「只能读取不能修改」,这里的修改仅指对泛型集合添加元素,如果是 remove(int index) 以及 clear 当然是可以的。
2.可以使用泛型通配符 ? super 来使泛型支持逆变,但是「只能修改不能读取」,这里说的不能读取是指不能按照泛型类型读取,你如果按照 Object 读出来再强转当然也是可以的。
被称为PECS法则,「Producer-Extends, Consumer-Super」

二.Kotlin的泛型

kotlin中主要使用inout关键字

out支持协变,等同于java的上界通配符? extend
in支持逆变,等同于java的下界通配符? super

out表示只输出,即只读in表示只输入,即只写

val textViews: List<out TextView>
val textViews: List<in TextView>

非集合类的使用,生产者

class Producer<T> {
	fun produce(): T {
		...
	}
}

val producer: Producer<out TextView> = Producer<Button>()
val textView: TextView = producer.produce()//相当于list的get

消费者

class Consumer<T>{
	fun consume(t: T) {
		...
	}
}

val consumer: Comsumer<in Button> = Consumer<TextView>()
consumer.consumer(Button(context)) // 相当于list的add

生产者的代码中可以把out放在类声明处,之后声明变量可以不用加out

class Producer<out T> {
	fun produce(): T {
		...
	}
}

//省略掉out
val producer: Producer<TextView> = Producer<Button>()
val textView: TextView = producer.produce()//相当于list的get

相同的,消费者的代码中,可以把in放在类声明处

class Consumer<in T>{
	fun consume(t: T) {
		...
	}
}

//省略in
val consumer: Comsumer<Button> = Consumer<TextView>()
consumer.consumer(Button(context)) // 相当于list的add

*
where关键字
java在使用<T extends>的时候(注意是T extends 不是 ? extends)

class Monster<T extends Animal>{}

还可以设置多个

class Monster<T extends Animal & Food>{}

kotlin中只是把extends换成了:

class Monster<T : Animal>{}

设置多个的时候

class Monster<T> where T: Animal,T: Food{}

如果Monster本身还有继承的时候

class Monster<T> : MonsterParent<T>
	where T:Animal

reified关键字

java中的泛型存在类型擦除

<T> void printIfTypeMatch(Object item) {
    if (item instanceof T) { // 报错
        System.out.println(item);
    }
}

解决方案就是再传递一个参数Class<T>类型

<T> void check(Object item, Class<T> type) {
    if (type.isInstance(item)) {
        System.out.println(item);
    }
}

Kotlin中可以使用reified关键字

inline fun <reified T> printIfTypeMatch(item: Any) {
    if (item is T) { 
        println(item)
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值