Generic Kotlin Notes (1)

Type parameter

Generics allow the definition of types with type parameters . When an instance of this type is created, the type parameters are replaced with concrete types called type arguments

Instance

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

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

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

In the above example, T is a type parameter , and the return type of the function uses a type parameter

the difference

  • Kotlin requires that type arguments are either explicitly specified or can be deduced by the compiler
  • Kotlin does not support primitive types, the type arguments must be defined
  • Java allows the use of generic types without type parameters (original ecological types) because it supports compatibility with older versions of code

Generic classes and functions

Generic class

Kotlin declares generic classes and generic interfaces by adding a pair of sharp check marks after the class name and putting the type parameters within the sharp check marks. Once declared, type parameters can be used in the body of the class like other types.

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

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

Summary: If the class inherits the generic class (implements the generic interface), it must provide a type argument for the generic parameter of the base type , which can be a concrete type or another type parameter:

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

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

Generic function

Generic functions have their own type parameters , these type parameters must be replaced with specific type arguments each time the function is called

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

Note: Ordinary (ie, non-extended) attributes cannot have type parameters, and cannot store multiple values ​​of different types in the attributes of a class, so there is no point in declaring generic non-extended functions

Type parameter constraints

Type parameter constraints may limit the generic functions and generic class as the type argument type; if the specified type is a generic type of the upper bound constraint parameter, in particular the initializing generic type, which corresponds to the type of solid The parameter must be this concrete type or its subtype

Example

// 函数声明
fun <T:Number> List<T>.sum() :T

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

In the above example, the constraint is defined by specifying the upper bound after the type parameter. Put the colon after the name of the type parameter, and the type as the upper bound of the type parameter immediately follows; once the upper bound of the type parameter T is specified, you can Use the value of type T as the value of its upper bound (type)

The type parameter is not empty or nullable

If the declaration is a generic class or generic function, any type argument, including those nullable type arguments, can replace its type parameters; type parameters without an upper bound will use the default Any? Upper Bound


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

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

Note : You can make the type parameter non-null by specifying any non-empty type as the upper bound, not just the type Any

Guess you like

Origin blog.csdn.net/xufei5789651/article/details/102837146