kotlin学习笔记——泛型及reified函数
来源:互联网 发布:下载语音助手软件 编辑:程序博客网 时间:2024/06/05 02:07
Kotlin学习笔记系列:http://blog.csdn.net/column/details/16696.html
kotlin中的泛型与java中的差不多
class TypedClass<T>(param : T){ ...}val s = TypedClass<String>("hello")
kotlin中可以简化模板代码,编译器可以自动推断类型,如
val s = TypedClass("hello")
但如果接收一个null,编译器无法推断类型,仍然需要指定类型,如
val s = TypedClass<String?>(null)
我们可以给泛型添加限制,如:
class TypeClass<T : Any>(param : T){ ...}
这时限制为非null类型,上面接收null的代码就会报错了。
我们也可以限制为某种类型的子类,与java中类似,如
class TypedClass<T : Context>(param : T){ ....}这样所有继承至Context的类可以使用,其他则不能。
泛型也可以使用在函数中,如
fun <T> do(param : T) List<T>{ ...}
泛型的变体
在java中,使用泛型时会遇到一些问题,比如使用集合的时候,如
List<String> list1 = Lists.newArrayList();List<Object> list2 = list1就会报错,虽然List<Object>有更弱的限制,因为如果编译器允许这种行为,后面如果出现下面的代码就一定会程序崩溃。
list2.add(5);String s = list2.get(0);但是在java中,我们可以使用addAll,如
List<Object> list2 = Lists.newArrayList();list2.addAll(list1)这时因为addAll的函数接收的参数是“Collection<? extends E> items”,这里就用到了泛型的协变。
为了解决类似的问题,为泛型增加了通配符,包括协变和逆变
协变(covariance)—— “? extends XXX” —— 表示限制为XXX及其子类
逆变(contravatiance)—— “? super XXX” —— 表示限制为XXX及其父类
这样就可以处理上面List的问题,如
List<? extends Object> list2 = list1;但是通配符都有它的限制,通配符定义的了使用场景变体(use-site variance),当我们使用它的时候都需要声明它。这表示我们每次声明一个泛型变量都需要增加模板代码。例如上面的代码就增加了一下额外的模板代码。
在kotlin中,我们可以使用内部声明变体(declaration-site variance)这种更简单的方式,来表示当我们定义一个类或接口时可以处理弱限制场景。
相比冗长的通配符,在kotlin中我们可以使用“out”来针对协变,使用“in”来针对逆变。如
class TypedClass<out T>{ ...}val obj1 = TypedClass<String>()val obj2 : TypedClass<Any> = obj1这段代码可以在kotlin中编译运行(最后一行实际上就相当于val obj2 : TypedClass<? extends Any> = obj1)
下面我们再来说说reified函数,它与泛型密切相关
比如我们启动一个activity代码:
val intent = Intent(MainActivity@this, javaClass<DetailActivity>)intent.putExtra(DetailActivity.ID, item.id)intent.putExtra(DetailActivity.NAME, item.name)startActivity(intent)
anko给我们提供了一个reified function,可以更简单的实现
startActivity<DetailActivity>(DetailActivity.ID to item.id, DetailActivity.NAME to item.name)
我们知道在java中使用泛型的时候,无法通过泛型来得到Class,一般我们会将Class通过参数传过去。
在kotlin中一个内联函数(inline)可以被具体化(reified),这意味着我们可以得到使用泛型类型的Class。
startActivity的源码如下:
public inline fun <reified T: Activity> Context.startActivity(
vararg params: Pair<String, String>) {
val intent = Intent(this, T::class.javaClass)
params forEach { intent.putExtra(it.first, it.second) }
startActivity(intent)
vararg params: Pair<String, String>) {
val intent = Intent(this, T::class.javaClass)
params forEach { intent.putExtra(it.first, it.second) }
startActivity(intent)
}
可以看到使用T::class.javaClass就可以得到使用泛型类型的Class。
startActivity是Context的内联函数,所以要在Context类中才可以使用,在其他地方使用则需要使用with函数:
with(context){ startActivity<...>(...)}
阅读全文
0 0
- kotlin学习笔记——泛型及reified函数
- kotlin学习笔记——内联函数
- kotlin学习笔记——集合及集合操作符
- kotlin学习笔记——类、函数、接口
- kotlin 泛型学习笔记
- Kotlin学习笔记——Kotlin中的null安全
- kotlin学习笔记001——kotlin简介
- Kotlin学习笔记——标准库kotlin
- Kotlin学习笔记——标准库kotlin.system
- Kotlin学习笔记——标准库kotlin.io
- Kotlin学习笔记——标准库kotlin.collections
- Kotlin学习笔记——安装配置kotlin
- kotlin学习笔记——Kotlin Android Extensions
- Kotlin笔记(三)——函数
- Kotlin学习笔记——基本类型
- Kotlin学习笔记——Day1
- Kotlin学习笔记——Day2
- Kotlin学习笔记——使用databinding
- Keil5生成BIN文件及HEX文件介绍
- html+css+js实现的简易下拉菜单
- VUE案例 todolist 上移下移置顶 删除
- 底部导航
- 《Node.js开发指南》微博程序中遇到的问题
- kotlin学习笔记——泛型及reified函数
- inno setup 5 默认选中添加快捷方式
- 有关 PHP 和 js 浮点运算的坑
- React/JSX及React Native 编码规范
- 100个原生js的常用方法
- leetcode 7.reverse integer
- HDU 2586 How far away ?——lca
- 听说你需要这样学习Redux
- 深入浅出单实例SINGLETON设计模式