Kotlin: 类型别名、属性名冲突解决

3,361 阅读6分钟

大风起兮云飞扬,
威加海内兮归故乡,
安得猛士兮守四方

                        ——刘邦 ·《卜算子》

你是否为一个变量类型过长而纠结过、吐槽过?那么这篇文章详细的讲解kotlin中的类型别名,以及实体类中属性名和关键字冲突的解决方法。让你告别这种方式

目录

一、类型别名

  • 关键字 : typealias
  • 作用 :为现有类型提供替代名称。 解决代码过于冗余与臃肿的问题

在开发中,命名过长、或者泛型等使代码过于冗余与臃肿,我们可以使用类型别名引入较短的名称,并使用新的名称替代原类型。这里从类名、函数参数、泛型三个方便讲解。值得注意的是:类型别名的定义必须在顶层声明

1.1、类名

例1 :普通类

// 类型别名,切记声明在顶部
typealias First = TypeAliasDemoTestFirst
typealias Second = TypeAliasDemoTestSecond

// 测试类
class TypeAliasDemoTestFirst{
    fun show(){
        println("name : ${this.javaClass.simpleName}")
    }
}
class TypeAliasDemoTestSecond{
    fun show(){
        println("name : ${this.javaClass.simpleName}")
    }
}

// 使用
fun main(){
    val first = First()
    first.show()

    val second = Second()
    second.show()
}

例2 :嵌套类与内部类

typealias NestA = DemoClassTestNest.A
typealias NestB = DemoClassTestNest.B

typealias InnerA = DemoClassTestInner.A
typealias InnerB = DemoClassTestInner.B

class DemoClassTestNest{
    class A{
        fun show(){
            println("name : ${this.javaClass.simpleName}")
        }
    }
    class B{
        fun show(){
            println("name : ${this.javaClass.simpleName}")
        }
    }
}

class DemoClassTestInner{
    class A{
        fun show(){
            println("name : ${this.javaClass.simpleName}")
        }
    }
    class B{
        fun show(){
            println("name : ${this.javaClass.simpleName}")
        }
    }
}

fun main(){
     val nestA = NestA()
    nestA.show()

    val nestB = NestB()
    nestB.show()

    val innerA = InnerA()
    innerA.show()

    val innerB = InnerB()
    innerB.show()
}

1.2、函数参数

当我们定义一个高阶函数,其参数过长的时候,也可以使用类型别名去美化代码。下面列举两个例子大家就明白了

例1 : 官网上的例子

// 定义一个返回值为Boolean类型的函数为另一个函数的参数,把这个函数参数定义为`Predicate<T>`的别名
typealias Predicate<T> = (T) -> Boolean    

// 定义的高阶函数
fun foo1(p : Predicate<Int>) = p(2)
fun foo2(p : Predicate<String>) = p("test")

fun main(){
    // 条件,即函数参数为{it > 0},返回值Boolean类型,其这里的it指的就是泛型T,确定为了Int型 
    val f1: (Int) -> Boolean = { it > 0 }
    // 即把2带入foo1函数中,经过上面的条件,判断出 2 > 0 故而应该输出为true
    println(foo1(f1))

    val f2 : (String) -> Boolean = {it == "xxx"}
    println(foo2(f2)) //这里输出为false, 很显然,"test" != "xxx"
}

输出结果:

true
false

例2 : 自定义一个难一点儿,安卓adapter中的item事件编写

// 这里可以注释,标明参数的含义
// typealias ItemListener = (Int, String)? -> Unit   

或者像这样定义:
typealias ItemListener = (pos : Int, item : String)? -> Unit   

class TestAdapter(val context : Context , val data: MutableList<String>)
: RecyclerView.Adapter<TestAdapter.TestViewHolder>(){

    private var mListener : ItemListener = null

    override fun onBindViewHolder(holder: TestViewHolder?, position: Int) {
        ...
        holder?.itemView?.setOnClickListener {
            mListener?.invoke(position, data[position])
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): TestViewHolder {
        return TestViewHolder(View.inflate(context,layoutId,parent))
    }

    override fun getItemCount()Int {
        return data.size
    }

    fun setOnItemClickListener(mListener : ItemListener){
        this.mListener = mListener
    }

    inner class TestViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView)
}

// 调用
TestAdapter(this,dataList).setOnItemClickListener { position, item ->
    Toast.makeText(this,"$position \t $item",Toast.LENGTH_SHORT).show()
}

1.3、泛型

例1 : 列表嵌套列表的情况

typealias MutListData = MutableList<MutableList<Int>>

fun main(){
    val data : MutListData = mutableListOf()
    val item1 = mutableListOf(1,3,5,7)
    val item2 = mutableListOf(2,4,6,8)
    data.add(item1)
    data.add(item2)

    data.asSequence().flatMap { it.asSequence() }.forEach { println("value : $it") }
}

输出结果 :

value : 1     value : 3   value : 5   value : 7   value : 2   value : 4   value : 6   value : 8   

例2 : 自定义泛型类,项目中常见的例子

typealias MapModelData<T> = Map<String, BaseModel<T>>

data class BaseModel<T>(val code : Int,
                    val msg : String,
                    val data : T){

     override fun toString(): String {
        return "BaseModel(code=$code, msg='$msg', data=$data)"
    }                    
}

fun main(){
    val dataModel : MapModelData<Int> = mutableMapOf()
    val model1 = BaseModel<Int>(1,"test 1"1)
    val model2 = BaseModel<Int>(2,"test2"2)
    dataModel.put("1" , model1)
    dataModel.put("2" , model2)

    dataModel.forEach { key, value ->
        println("key : $key value : ${value.toString()}")
    }
}

输出结果:

key : 1 value : BaseModel(code=1, msg='test 1', data=1)
key : 2 value : BaseModel(code=2, msg='test2', data=2)

二、属性名冲突解决

在开发中,处理Json字符串转换成实体类的时候,会出现属性名和关键字冲突的问题。下面实现Javakotlin的解决方案。

2.1、Java的解决方案

Java使用@SerializedName注解

public class Test{
    private int id;
    private String name;
    @SerializedName("swicth")
    private int s;
}

2.2、Kotlin的解决方案

Kotlin中,无需像Java一样引注解,只需要把属性名包括在符号( `` )中即可。这个符号是英文输入法下的Tab键上面的一个键。

data class TestBean(val id : Int,
                    val name : String,
                    val `package` : String)

这种情况在开发中一般不会出现。因为开发人员都会注重命名规范。但是偶尔出现的时候我们可以使用上面的知识去解决。

三、总结

上面的知识点虽然很简单,在开发中也不是很常用,但是对于项目开发而言,类型别名还是请大家尽量掌握,因为其在代码美观、简洁上是很有作用的,不过如果滥用的话,会对代码维护提升不小的难度

本文已收录至GitHub: Jetictors/KotlinLearn,欢迎star

文章持续更新中,可以微信搜索「J佬杂谈 」第一时间阅读, 大家的三连击是对老J最好的动力了,你确定不来一波吗?

如果本篇博客有任何错误和建议,欢迎人才们留言


啊喂,五指菇娘啊,拿着手机扫描一下吧!