Kotlin笔记之泛型(一)

类型参数

泛型允许定义带类型形参的类型,当这种类型的实例被创建出来的时候,类型形参被替换成称为类型实参的具体类型

实例

// 源码listOf函数声明
fun <T> listOf(vararg elements: T): List<T>

val list=listOf("hello","world") // 编译器推导

val list= listOf<String>()// 显示说明

上例中 T类型形参 ,并且函数的返回类型使用了类型形参

区别

  • Kotlin 要求类型实参要么被显示地说明,要么能被编译器推导推导出来
  • Kotlin 不支持原生态类型,类型实参必须定义
  • Java 允许使用没有类型参数的泛型类型(原生态类型),因为支持老版本代码兼容

泛型类和函数

泛型类

Kotlin 通过在类名称后加上一对尖对号,并把类型参数放在尖对号内来声明泛型类及泛型接口。一旦声明之后,就可以在类的主体内像其他类型一样使用类型参数。

// 泛型类
class Gen<T>(private var t: T) {
    
    
    fun  getValue() :T{
    
    
        return t
    }
}

// 泛型接口
interface List<T>{
    
    
  public operator fun get(index: Int): T
}

小结: 如果类继承了泛型类(实现了泛型接口),就得为基础类型的泛型形参提供了一个类型实参,它可以是具体类型或者另一个类型形参:

class GenList:List<String>{
    
    
 override fun get(index :Int):String=...
}

class ArrayList<T>:List<T>{
    
    
override fun get(index :Int):T=...
}

泛型函数

泛型函数有它自己的类型形参,这些类型形参在每次函数调用时都必须替换成具体的类型实参

fun <T> printMessage(msg :T){
    
    
    when (content) {
    
    
       is Int ->{
    
    "该信息数据类型是整型"}
       else ->{
    
    "该信息数据类型不是整型"}
    }
}

注意: 普通(即非拓展)属性不能拥有类型参数,不能在一个类的属性中存储多个不同类型的值,因此声明泛型非拓展函数没有任何意义

类型参数约束

类型参数约束可以限制作为泛型类和泛型函数的类型实参的类型;如果把一个类型指定为泛型类型形参的上界约束,在泛型类型具体的初始化中,其对应的类型实参就必须是这个具体类型或者它的子类型

示例

扫描二维码关注公众号,回复: 12573159 查看本文章
// 函数声明
fun <T:Number> List<T>.sum() :T

// 具体类型实参继承了Number,函数调用是允许的
println(listOf(1,2,3).sum())

上例中,通过在类型参数后指定上界来定义约束,把冒号放在类型参数名称之后,作为类型形参上界的类型紧随其后;一旦指定了类型形参T的上界,就可以把类型T的值当作它的上界(类型)的值使用

类型参数非空、可空

如果声明的是泛型类或者泛型函数,任何类型实参,包括那些可空的类型实参,都可以替换它的类型形参;没有指定上界的类型形参将会使用Any?这个默认上界


// 类型参数可空  默认上界的类型形参是Any?
class Person<T>{
    
    
  fun name(value :T){
    
    
    value?.hashcode()
  }
}

// 类型参数非空   默认上界的类型形参是Any
class Person<T:Any>{
    
    
  fun name(value :T){
    
    
    value?.hashcode()
  }
}

注意:可以通过指定任意非空类型作为上界,来让类型参数非空,不光是类型Any

猜你喜欢

转载自blog.csdn.net/xufei5789651/article/details/102837146