博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Kotlin 学习笔记09
阅读量:6349 次
发布时间:2019-06-22

本文共 3186 字,大约阅读时间需要 10 分钟。

泛型

  • 泛型类型参数 class Map<K,V> 可以用具体的类型实参实例化。 IDE推到类型
listOf("Jack Ma","Bob") //IDE推导出类型泛型是String复制代码
  • 泛型函数与属性
fun 
List
.silent(indicate: IntRange):List
= listOf
()//调用val toList = ('A'..'Z').toList()list.silent(1..3)public inline fun
Iterable
.filter(predicate: (T) -> Boolean): List
{ return filterTo(ArrayList
(), predicate)}toList.filter{it}//这里的it就是根据toList推到出来的,在这里it => List
it = Char类型复制代码
  • 声明泛型类
interface List
{ operator fun get(index: Int): T}复制代码

类型参数约束

因为Int、Double都继承自Number,所以可以拥有sum()方法。一旦指定了上界,就可以在方法中调用上界的方法。

  • 指定多个约束
fun 
ensureTraningPriod(seq: T) where T : Char, T : Appendable {
//报错,第一个T?}复制代码

让类型形参非空

没有指定上界的类型形参,将会使用Any?这个上界。

class procress
(){ fun procress(value: T){ value?.hashCode()//默认是可空类型,需要作出判断再处理 }}复制代码
  • 如果你想保证 类型形参为非空类型,可以指定一个上界
class procress
(){ fun procress(value: T){ value.hashCode() }}复制代码

运行时泛型:擦除和实化类型参数

在JVM运行时候,泛型是会被擦除的。

*运行时的泛型 kotlin不允许使用没有指定泛型的类型参数

fun print(c:Collection
){ if (c is List
) {
//书上说,这里不会报错,实际上IDE会报错? println(c.sum()) }}复制代码

声明带实化(实例化)类型参数的函数

fun 
isA(value: Any) = value is T //这里会报错,在调用函数体,不能确定用的类型实参。复制代码

避免上述情况,可以使用内联函数-》inline修饰,类型参数可以实例化

inline fun 
isA(value: Any) = value is T//这里编译正常,使用了内联函数,类型实参使用了reified关键字。复制代码

原理:内联函数生成字节码插入每一个调用地方,每次调用编译器都知道你需要调用类型实参的具体类

使用实化类型参数代替类引用

实化类型参数方法

  • 实化类型参数转换(使用 is !is as as?)
  • 使用Kotlin反射API
  • 获取对应的Java.Lang.Class
  • 作为调用其他方法的类型实参

泛型和子类型化

  • 为什么存在变形:为了给函数传递实参 这样可以很方便调用,而且编译器在发现不安全地方会报错

类、类型和子类型

变量的类型规定了该变量的可能值,类型和类是不一样的:

  • 非泛型类-》var x = String 或者 var x = String? 说明了一个Kotlin类都可以用于构造至少2种类型。
  • 泛型类 -》 List List List<List> 等等
  • 超类和子类是反义词
fun testPrint(i: Int) {        val num: Number = i//这里不会报错,因为Int是Number的子类        fun f(str: String) {        }        f(num)//这里会报错因为Int不是String的子类    }复制代码
  • 类型和子类型是不一样的。eg: 非空类型A可以是空类型的子类,但是反过来不是。

协变:保留子类型关系

一个协变类是一个泛型类

open class Animal {    fun feed() {}}class Herd
{ val size get() = 3 operator fun get(i:Int) :T = {}//定义get约定}fun feedAll(animals:Herd
){ for (i in 0 until animals.size) animals[i].feed()}//class Cat:Animal(){ fun clearLitter(){}}fun takeCareOfCat(cats:Herd
){ for (i in 0 until cats.size){ cats[i].clearLitter() cats[i].feed() } feedAll(cats) //这里会报错}复制代码
  • 类型参数T上关键字的2个含义
  1. 子类型化会被保留
  2. T只能在out位置上

List<Interface>接口。在kotlin,List是只读的,只有返回值T,没有把类型为T的元素存储在列表的方法。所以他是协变的比如:

interface ListStr
: Collection
{ //声明T为协变 operator fun get(index: Int): T //这里的类型参数只出现在返回值,所以是协变}复制代码

不能把MutableList<T>在他类型声明成协变,因为他基友接收类型T值作为参数方法,也有返回类型T(T出现在inout两种位置上) 需要注意构造方法中的var变量,如果用var声明变量有类型T,则不能使用out泛化


逆变:反转子类型化

逆变

interface Comparetor
{ // fun compare(e1:T,e2:T):Int {
/**/}}复制代码

in关键字的意思是:对应类型的值是传递进来给这个类的方法,并且被这个类消费的。意味着子类型化被反转,而且T只能是留在in位置

一个类可以在一个类型参数上协变,在另外一个参数上逆变。

interface Fuction1
{ operator fun invoke(p: P): R}复制代码

上面可以使用(P)->R表示更直观

点变形:在类型出现的地方指定变形

比如:Java中(? extends和? super)

End

转载于:https://juejin.im/post/5c4014a051882525ed5c48f7

你可能感兴趣的文章
关于网络上java,php和.net的“口角之争“的一点想法 !
查看>>
python 第二周(第十三天) 我的python成长记 一个月搞定python数据挖掘!(21) -正则表达式re...
查看>>
[POI2011]SEJ-Strongbox
查看>>
20文件
查看>>
Android开发Intent应用概述
查看>>
【Go】并发编程
查看>>
VMware虚拟化NSX-Manager命令行更改admin用户密码
查看>>
悦纳自己
查看>>
python字符串函数
查看>>
ORM框架Hibernate (四)MyEclipse Hibernate Tool 逆向生成实体类
查看>>
去掉iphone连接电脑时会出现的弹出窗口
查看>>
【python】-- web开发之HTML
查看>>
vs2015 去除 git 源代码 绑定
查看>>
解决firefox的button按钮文字不能垂直居中
查看>>
网络协议端口号详解
查看>>
大话数据结构读后感——第一章
查看>>
各种排序
查看>>
ts 格式化日期输出
查看>>
Optional
查看>>
sed 命令编辑文本
查看>>