kotlin学习之泛型(十四)

目录


本小结介绍的是kotlin的泛型,先从Java的泛型开始介绍:

kotlin中使用泛型的方式跟Java相差不大:

class Box<T>(t: T) {
    var value = t
}

// 使用
val box: Box<Int> = Box<Int>(1)
//kotlin可以自动推断类型
val box2 = Box(1)

Java

Java中,在没有通配符上下界的情况下,是不可变的,也就是说,在指定泛型类型后,Java就能在编译期确定泛型的类型,防止运行时出现异常。为了泛型的灵活性,提出了通配符上下界。

  1. 通配符上界,只能从中读取元素,不能添加元素,称为生产者(Producers),用<? extends T>表示。
List<String> strs = new ArrayList<String>();
strs.add("0");
strs.add("1");
List<? extends Object> objs = strs;
objs.get(0); // 可以获取
objs.add(1); // 错误,不能添加

之所以不能添加元素的原因很明显,因为没法确定添加的实例类型跟定义的类型是否匹配。

  1. 通配符下界,只能添加元素,不能直接读取下界类型的元素,称为消费者(Consumers),用<? super T>表示。
List<String> strs = new ArrayList<String>();
strs.add("0");
strs.add("1");
List<? super String> objs = strs;
objs.add("1");
objs.set(0, "2");
//String s = objs.get(0); get不能直接得到String类型的对象
Object s = objs.get(0);

不得不说,这样做法是合理的,但是是可能会出错的。来看看Kotlin是怎么实现类似的情况的。

kotlin

在Kotlin中,使用声明位置变异来解决这种问题:

  1. 使用out关键字标识的泛型T,只能作为返回值,而不能作为传入参数。
abstract class Source<out T> {
    // 使用out的话,T只能作为返回值
    abstract fun nextT(): T
    // 不能作为传入参数,下面会报错
    // abstract fun add(value: T)
}

fun demo(strs: Source<String>) {
    val objects: Source<Any> = strs
}

这种做法实际上就是对应Java中的<? extends T>,因为只能作为返回值而不能作为参数,所以不会出现Java可能出现的运行异常。

  1. 使用in关键字标识的泛型T,只能作传入参数,而不能作为返回值。
abstract class Source<in T> {
    // 使用in的话,只能作为传入参数,不能作为返回值
    // abstract fun nextT(): T
    abstract fun add(value: T)
}

fun demo(strs: Source<Number>) {
    val objects: Source<Double> = strs // Double是Number的子类型
}

这样是不是更加合理了呢? 用一句概括Kotlin的这种做法,就是:

Consumer in, Producer out!

Kotlin同样支持泛型函数:

fun <T> singletonList(item: T): List<T> {
}

fun <T> T.basicToString() : String {  // extension function
}

使用的时候,在函数名称后面指定具体的类型参数:
val l = singletonList<Int>(1)

Kotlin的泛型约束和类的继承一样,使用:代替extends对泛型的的类型上界进行约束:

class SwipeRefreshableView<T : View>{}

同时Kotlin支持多个类型的上界约束,,使用where关键字:

class SwipeRefreshableView<T>
    where T : View,
          T : Refreshable {
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值