本篇笔记主要记录过去几年 工作所需Kotlin的进阶技术,查漏补缺
- 更多参考:https://www.yiibai.com/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){
    //处理点击事件
}
