当前位置:网站首页>Kotlin advanced generic

Kotlin advanced generic

2022-06-25 09:52:00 seevc

stay Android We often use generics in development , Such as :List、Map、Set、Adapter etc. , So in Kotlin Generics are also supported in .
What is generics ?
Generic : Postpone type specific work until the object is created or the method is called .

One 、Kotlin Define generic methods in

stay Kotlin Generic types are defined in Java equally , There are two ways :

  • Defined on class
  • Defined in a function
    Define examples on classes :
class MagicBox<T>(val item: T) {
    var available = false

    fun fetch(): T? {
        return item.takeIf { available }
    }
}

Defined in a function

class MagicBox<T>(val item: T) {
    var available = false

    /**
     *  Add normal form type to function , similar Java
     */
    fun <R> fetch(anotherGenericity: (T) -> R): R? {
        return anotherGenericity(item).takeIf { available }
    }
}

Two 、Kotlin Define constraint generics in

Kotlin Defines constraint generics and Java < T extend XXX> Generics are defined in a similar way , Indicates that the type specified by a generic type must be a class of the specified type or a subclass that inherits the specified type class . This sentence is a little convoluted , for instance : Define a generic type class A<T : B>(), Generics passed in T It has to be for B perhaps B Subclasses of . The complete example is as follows :

// Define a constraint generic 
private class ConstraintMagicBox<T:Human>(item:T){

}

// Define a parent class 
private open class Human(val name: String,val age:Int)
// Define a Human Subclasses of classes 
private class Male(name: String,age: Int):Human(name, age)
// Define a Human Subclasses of classes 
private class Female(name: String,age: Int):Human(name, age)

fun main() {
    // A fellow Human Type can be passed in 
    val male = ConstraintMagicBox(Male("Jack", 20))
    val female = ConstraintMagicBox(Female("Jim", 20))
}

3、 ... and 、Kotlin Define variable number parameter generics

This is similar to Java Define variable parameters for methods in (private void method(int.. num)), stay Kotlin The way to define in depends on keywords **vararg**, Both normal functions and constructors can use .
Examples are as follows :

private class VarMagicBox<T : VarHuman>(vararg val items: T) {

    // From items Get data in , among items Type not Array
    fun fetch(index: Int): T? {
        return items.getOrNull(0)
    }

    // Add variable arguments to the function 
    fun fetch(vararg indexs: Int):List<T>{
        indexs.takeIf {
            indexs.isNotEmpty()
        }.run {
            return items.filterIndexed { index, t ->
                indexs.contains(index)
            }
        }
    }
}

private open class VarHuman(val name: String, val age: Int)

Four 、Kotlin of use in、out Modifying generics

stay Java Define a List in , Specify a specific type , When creating an instance, you can only new Examples of this type , unable new Create an instance of a subclass or parent class ,
Example :
ArrayList<String> list = new ArrayList<CharSequence>()
perhaps
ArrayList<CharSequence> list = new ArrayList<String>()
These two ways of writing are in JAVA Is not supported , The correct way to write is :ArrayList<String> list = new ArrayList<String>().
But in Kotlin Can support .
Of course, the generic example defined above does not support , that Kotlin How can we support this way of writing ?
because Kotlin There are two important keywords in in( Covariance )out( Inversion )
Let's take a look at how the following two keywords can support the above writing .
Very simple to use , Let's start with an example , Take a look at the usage :

//out Decorated generics   Only use generics as function return values 
// effect : Let subclass generic objects assign values to parent generic objects 
interface OutTest<out T>{
    fun outTest():T
}

//in Decorated generics   Only use generics as function arguments , A generic cannot be treated as a return value 
// effect : The parent generic object can be assigned to the child generic object 
interface InTest<in T>{
    fun inTest(param : T)
}

The test code is as follows :

open class Food()
open class FastFood():Food()
class Hamburg():FastFood()

class FastFoodStore() : OutTest<FastFood>{
    override fun outTest(): FastFood {
        println("FastFoodStore ----------")
        return FastFood()
    }
}

class HamburgStore():InTest<FastFood>{
    override fun inTest(param: FastFood) {
        println("HamburgStore-----------")
    }
}

fun main() {
    // Subclass objects can be passed to parent generic objects  out
    val food1 : OutTest<Food> = FastFoodStore()

    // A parent class object can be passed to a child class generic object  in
    val food2 : InTest<Hamburg> = HamburgStore()
}

keyword in、out Use summary
There are two main points :

  • out Decorated generics can only be used in Function return value Use in ,in Decorated generics can only be used in The parameters of the function Use in ;
  • out Decorated generics can only The subclass generic object is assigned to the parent generic object ,in Decorated generics can only The parent class generic object is assigned to the child class generic object , As shown in the figure below ;
    image.png

Welcome to leave a message for us to exchange and learn from each other !


Sample source address kotlin_demo

原网站

版权声明
本文为[seevc]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202200547582950.html