Kotlin进阶笔记

hloong 于 2021-04-18 发布

本篇笔记主要记录过去几年 工作所需Kotlin的进阶技术,查漏补缺

0,Kotlin泛型和注解

泛型

fun main(){
    println(Milk().taste().price)
    BlueColor(Blue()).printColor()
    test()
}

interface Drinks<T>{
    fun taste():T
    fun price(t:T)
}

class Price{
    val price = 5
}

class Milk:Drinks<Price>{
    override fun taste():Price{
        println("Price")
        return Price()
    }
    override fun price(t:Price){
        println("Milk price:${t.price}")
    }
}

/**
 * 泛型类
 */
abstract class Color<T>(var t:T){
    abstract fun printColor()
}
class Blue{
    val color = "Blue"
}
class BlueColor(t:Blue):Color<Blue>(t){
    override fun printColor(){
        println("color: ${t.color}")
    }
}
/* 泛型方法 */
fun <T> fromJson(json:String,tClass:Class<T>):T?{
    val t:T? = tClass.newInstance()
    return t
}
/* 泛型约束 */
fun <T:Comparable<T>?> sort(list:List<T>?):Unit{}
fun test(){
    sort(listOf(5,2,3,4))
    val listString = listOf("a","b","c")
    val list = listTest(listString,"a")//大于a的才输出
    println(list)
}
//泛型多个上界的情况,用where限制
fun <T> listTest(list:List<T>,threshold:T):List<T>
    where T:CharSequence,
          T:Comparable<T> {
    return list.filter{it > threshold}.map{it}
}

/* Price
 * 5
 * color: Blue
 * [b, c] 
 */

在Kotlin中Out代表协变,in代表逆变,以下为对比:

//kotlin使用处协变
fun sumOfList(list:List<out Number>)
//Java上界通配符
void sumOfList(List<? extends Number> list)

//kotlin使用处逆变
fun addNumbers(list:List<in Int>)
//java 下界通配符
void addNumbers(List<? super Interger> list)

注解

@Target(AnnotationTarget.CLASS)
annotation class ApiDoc(val value:String)

@ApiDoc("modify class")
class Box{
    // @ApiDoc("修饰字段")
    val size = 6
    // @ApiDoc("修饰方法")
    fun test(){
    }
}

实例: 通过注解判断api是get还是post

fun main(){
    fire(ApiGetArt())
}

public enum class Method{
    GET,POST
}

@Target(AnnotationTarget.CLASS)
annotation class HttpMethod(val method:Method)

interface Api{
    val name:String
    val version:String
        get() = "1.0"
}

@HttpMethod(Method.GET)
class ApiGetArt:Api{
    override val name:String
        get() = "/api.getArt"
}

fun fire(api:Api){
    val  annotation = api.javaClass.annotations
    val method = annotation.find{it is HttpMethod } as? HttpMethod
    println("通过注解得到该接口需要通过: ${method?.method} 方法请求")
}
// 返回的结果:
// 通过注解得到该接口需要通过: GET 方法请求

1,Kotlin中的扩展Extensions

Why?为啥要用扩展?

泛型扩展方法

//更换一个数组的坐标元素值
fun main(){
    printSwap()
}

fun printSwap(){
    val list = mutableListOf(2,6,7)
    list.swapInt(0,1)
    println("list.swapInt(0,1):${list}")

    val listString = mutableListOf("ab","c")
    listString.swapT(0,1)
    println("listT.swapT(0,1):${listString}")
}
//单扩展Int
fun MutableList<Int>.swapInt(index1:Int,index2:Int){
    val temp = this[index1]
    this[index1] = this[index2]
    this[index2] = temp
}
//对单扩展做泛型,支持多种类型参数
fun <T> MutableList<T>.swapT(index1:Int,index2:Int){
    val temp = this[index1]
    this[index1] = this[index2]
    this[index2] = temp
}
/** 结果
 * list.swap(0,1):[6, 2, 7]
 * listT.swap(0,1):[c, ab]
 */

扩展属性

fun main(){
    println("字符串「12ABC的最后一个字」:${"12ABC的最后一个字".lastChar}")
}
 //为String添加一个lastChar属性,用于获取字符串的最后一个字符
 val String.lastChar:Char get() = this.get(this.length-1)
 //结果:字符串「12ABC的最后一个字」: 字

为伴生对象添加扩展

/**为伴生对象添加扩展 */
fun main(){
    Jump.print("伴生对象扩展")
}
 class Jump{
    companion object{}
 }
 fun Jump.Companion.print(str:String){
    println(str)
 }
 //结果: 伴生对象扩展

2,Kotlin中的常用扩展方法

let

主要作用:避免null操作,限制作用域

fun main(){
    testLet(null)
    testLet("Let")
}
fun testLet(str:String?){
    //避免为null的操作,let里面永远不为null
    str?.let{
        println(it.length)
    }
    //限制作用域
    str.let{
        val str2 = "let 作用域"
        println(it+str2)
    }
 }
 // 返回结果:
 // nulllet 作用域
 // 3
 // Letlet 作用域

Run

省事,在run代码块里面可以直接调用函数的属性

fun main(){
    testRun(People("HL",30))
}
data class People(val name:String,val age:Int)
 fun testRun(p:People){
    p.run{
        println("Name:$name,Age:$age")
    }
 }
 //结果:Name:HL,Age:30

Apply

调用某个对象的apply函数,在函数范围类可以任意调用该对象的任意方法,并返回该对象

fun main(){
    testApply()
}
fun testApply(){
    ArrayList<String>().apply{
        add("a")
        add("b")
    }.let{
        println(it)
    }
 }
 //结果:[a,b]

实战代码实例(此例类似Android中Kotlin的layout扩展)

使用kotlin扩展为控件绑定监听器减少模板代码


fun <T:View> Activity.find(@IdRes id:Int):T{
    return findViewById(id)
}
fun Int.onClick(activity:Activity,click:()->Unit){
    activity.find<View>(this).apply{
        setOnClickListener{
            click()        
        }    
    }
}

//上面代码应用在Activity中:
val tv = find<TextView>(R.id.tv)
R.id.tv.onClick(this){
    //处理点击事件
}