| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> kotlin基础学习笔记第九章——泛型 -> 正文阅读 |
|
[移动开发]kotlin基础学习笔记第九章——泛型 |
? ? ? ? 实化类型参数允许你在运行时的内联函数中引用作为类型实参的具体类型(对普通的类和函数来说,这样行不通,因为类型实参在运行时会被擦除)。 ?????????声明点变型可以说明一个带类型参数的泛型类型,是否是另一个泛型类型的子类型或者超类型,它们的基础类型相同但类型参数不同。例如,它能调节是否可以把List<Int>类型的参数传给期望List<Any>的函数。使用点变型在具体使用一个泛型类型时做同样的事,达到和java通配符一样的效果。 ? ? ?一、泛型类型参数? ? ? ?泛型允许你定义带类型形参的类型。当这种类型的实例被创建出来的时候,类型形参被替换成称为类型实参的具体类型。例如,如果有一个List类型的变量,弄清楚这个列表中可以存储哪种事物是很有意义的。类型形参可以准确清晰地进行描述,就像这样“这个变量保存了字符串列表”,而不是“这个变量保存了一个列表”。kotlin说明“字符串列表”的语法和java看起来一样:List<String>。还可以给一个类声明多个类型形参。例如,Map类型就有键类型和值类型两个类型形参:class Map<K, V>。我们可以用具体的类型实参来实例化它:Map<String, Person>。目前,所有概念都和java没什么不一样。 ? ? ? ? 和一般类型一样,Kotlin编译器也常常能推导出类型实参:
? ? ? ? ?因为传给listOf函数的两个值都是字符串,编译器能推导出你正在创建一个List<String>。另一方面,如果你想创建一个空的列表,这样就没有任何可以推导出类型实参的线索,你就得显式地指定它(类型实参)。就创建列表来说,既可以选择在变量声明中说明泛型的类型,也可以选择在创建列表的函数中说明类型实参。参看下面的例子: ? ? ? ? 1、泛型函数和属性? ? ? ? 如果要编写一个使用列表的函数,希望它可以在任何列表(通用的列表)上使用,而不是某个具体类型的元素的列表,需要编写一个泛型函数。泛型函数有它自己的类型参数。这些类型形参在每次函数调用时都必须替换成具体的类型实参。 ? ? ? ? 大部分使用集合的库函数都是泛型的。来看看slice函数:这个函数返回一个只包含在指定下标区间内的元素。 ? ? ? ? ?接收者和返回类型用到了函数的类型形参T,它们的类型都是List<T>。当你在一个具体的列表上调用这个函数时,可以显式地指定类型的实参。但大部分情况下你不必这样做,因为编译器可以推导出类型。 ? ? ? ? 这两次调用的结果都是List<Char>。编译器把函数返回类型List<Char>中的T替换成了推导出来的类型Char。 ? ? ? ? 再来看看filter函数的声明,它接收了一个函数类型(T)-> Boolean的参数。 ?????????这个例子中自动生成的lambda参数it的类型是String。编译器必须把它推导出来:毕竟,在函数声明中lambda参数是泛型类型T。编译器推断T就是String,因为它知道函数应该是list<T>上调用,而它的接收者readers的真实类型是List<String>。 ? ? ? ? 可以给类或接口的方法、顶层函数,以及扩展函数声明类型参数。 ? ? ? ? 不能声明泛型非扩展属性。 ? ? ? ? 2、声明泛型类?????????和java一样,kotlin通过在类名称后加上一对尖括号,并把类型参数放在尖括号内来声明泛型类及泛型接口。一旦声明之后,就可以在类的主体内像其他类型一样使用类型参数。我们来看看标准java接口List如何使用Kotlin来声明。 ? ? ? ? 如果你的类继承泛型类(或者实现泛型接口),你就得为基础类型的泛型形参提供一个类型实参。它可以是具体类型或者另一个类型形参。? ? ? ? ? ?StringList类被声明成只能包含String元素,所以它使用String作为基础类型的类型参数。子类中的任何函数都要用这个正确的类型替换掉T。所以在StringList中你会得到函数签名get(Int): String,而不是fun get(Int): T。 ? ? ? ? 而类ArrayList定义了它自己的类型参数T并把它指定为父类的类型实参。注意ArrayList<T>中的T和List<T>中的T不一样,它是全新的类型形参,不必保留一样的名称。 ? ? ? ? 一个类甚至可以把它自己作为类型实参引用。实现Comparable接口的类就是这种模式的经典例子。任何可以比较的元素都必须定义它如何与同样类型的对象比较:? ????????? String类实现了Comparable泛型接口,提供类型String给类型实参T。 ? ? ? ? 迄今为止,泛型和java中的看起来差不多。? ?? ????????3、类型参数约束? ? ? ? 类型参数约束可以限制作为(泛型)类和(泛型)函数的类型实参的类型。? ? ? ?? ? ? ? ? ?如果你把一个类型指定为泛型类型形参的上界约束,在泛型类型具体的初始化中,其对应的类型实参就必须是这个具体类型或者它的子类型。 ? ? ? ? 你是这样定义约束的,把冒号放在类型参数名称之后,作为类型形参上界的类型紧随其后。在java中用的是关键字extends来表达一样的概念: ? ? ? ? 这次函数调用是允许的,因为具体类型实参(下面这个例子中是Int)?继承了Number。 ? ? ? ? 一旦指定了类型形参T的上界,你就可以把类型T的值当作它的上界(类型)的值使用。例如,可以调用定义在上界类中的方法:? ? ? ? ?现在让我们编写一个找出两个条目中最大值的泛型函数。因为只有在可以相互比较的条目之中才能找出最大值,需要在函数签名中说明这一点。做法如下: ? ? ? ? 当你试图对不能比较的条目调用max方法时,代码不能编译: ? ? ? ? T的上界是泛型类型Comparable<T>?。前面已经看到了,String类继承了Comparable<T> ,这样使得String变成了max函数的有效类型实参。 ? ? ? ? 记住,first > second的简写形式会根据kotlin的运算符约定被编译成first.compareTo(second) > 0。这种比较之所以可行,是因为first的类型T继承自Comparable<T>,这样你就可以 比较first和另外一个类型T的元素。 ? ? ? ? 极少数情况下,需要在一个类型参数上指定多个约束,这时你需要使用稍微不同的语法。例如下面这个代码清单用泛型的方式保证给定的CharSequence以句号结尾。标准StringBuilder类和CharBuffer类都适用。 ? ? ? ? 这种情况下,可以说明作为类型实参的类型必须实现CharSequence和Appendable两个接口。这意味着该类型的值可以使用访问数据(endsWith)和修改数据(append)两种操作。 ? ? ? ? 4、让类型形参非空?????????? ? ? ? ?如果你声明的是泛型类或者泛型函数,任何类型实参,包括那些可空的类型实参,都可以替换它的类型形参。事实上,没有指定上界的类型形参将会使用Any?这个默认的上界。来看看这个例子: ? ? ? ? process函数中,参数value是可空的,尽管T并没有使用问号标记。下面这种情况是因为Processor类具体初始化时T能使用可空类型: ? ? ? ? ?如果你想保证替换类型形参的始终为非空类型,可以通过指定一个约束来实现。如果你除了可空性之外没有任何限制,可以使用Any代替默认的Any?作为上界: ? ? ? ? ?约束<T: Any>确保了类型T永远都是非空类型。编译器不会接收代码Processor<String?>,因为类型实参String?不是Any的子类型(它是Any?的子类型,一种更普通的类型): ? ? ? ? 注意,可以通过指定任意非空类型作为上界,来让类型参数非空,不光是类型Any。? ? |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/22 18:14:55- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |